LCOV - code coverage report
Current view: top level - layout/style - nsCSSValue.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 563 1820 30.9 %
Date: 2017-07-14 16:53:18 Functions: 77 159 48.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* representation of simple property values within CSS declarations */
       8             : 
       9             : #include "nsCSSValue.h"
      10             : 
      11             : #include "mozilla/ServoStyleSet.h"
      12             : #include "mozilla/StyleSheetInlines.h"
      13             : #include "mozilla/Likely.h"
      14             : #include "mozilla/MemoryReporting.h"
      15             : #include "mozilla/css/ImageLoader.h"
      16             : #include "CSSCalc.h"
      17             : #include "gfxFontConstants.h"
      18             : #include "imgIRequest.h"
      19             : #include "imgRequestProxy.h"
      20             : #include "nsIDocument.h"
      21             : #include "nsCSSProps.h"
      22             : #include "nsNetUtil.h"
      23             : #include "nsPresContext.h"
      24             : #include "nsStyleUtil.h"
      25             : #include "nsDeviceContext.h"
      26             : #include "nsStyleSet.h"
      27             : #include "nsContentUtils.h"
      28             : 
      29             : using namespace mozilla;
      30             : using namespace mozilla::css;
      31             : 
      32             : static bool
      33           1 : MightHaveRef(const nsString& aString)
      34             : {
      35           1 :   const char16_t* current = aString.get();
      36         119 :   for (; *current != '\0'; current++) {
      37          59 :     if (*current == '#') {
      38           0 :       return true;
      39             :     }
      40             :   }
      41             : 
      42           1 :   return false;
      43             : }
      44             : 
      45         252 : nsCSSValue::nsCSSValue(int32_t aValue, nsCSSUnit aUnit)
      46         252 :   : mUnit(aUnit)
      47             : {
      48         252 :   MOZ_ASSERT(aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
      49             :              aUnit == eCSSUnit_EnumColor,
      50             :              "not an int value");
      51         252 :   if (aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
      52             :       aUnit == eCSSUnit_EnumColor) {
      53         252 :     mValue.mInt = aValue;
      54             :   }
      55             :   else {
      56           0 :     mUnit = eCSSUnit_Null;
      57           0 :     mValue.mInt = 0;
      58             :   }
      59         252 : }
      60             : 
      61         783 : nsCSSValue::nsCSSValue(float aValue, nsCSSUnit aUnit)
      62         783 :   : mUnit(aUnit)
      63             : {
      64         783 :   MOZ_ASSERT(eCSSUnit_Percent <= aUnit, "not a float value");
      65         783 :   if (eCSSUnit_Percent <= aUnit) {
      66         783 :     mValue.mFloat = aValue;
      67         783 :     MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
      68             :   }
      69             :   else {
      70           0 :     mUnit = eCSSUnit_Null;
      71           0 :     mValue.mInt = 0;
      72             :   }
      73         783 : }
      74             : 
      75           0 : nsCSSValue::nsCSSValue(const nsString& aValue, nsCSSUnit aUnit)
      76           0 :   : mUnit(aUnit)
      77             : {
      78           0 :   MOZ_ASSERT(UnitHasStringValue(), "not a string value");
      79           0 :   if (UnitHasStringValue()) {
      80           0 :     mValue.mString = BufferFromString(aValue).take();
      81             :   }
      82             :   else {
      83           0 :     mUnit = eCSSUnit_Null;
      84           0 :     mValue.mInt = 0;
      85             :   }
      86           0 : }
      87             : 
      88           0 : nsCSSValue::nsCSSValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
      89           0 :   : mUnit(aUnit)
      90             : {
      91           0 :   MOZ_ASSERT(UnitHasArrayValue(), "bad unit");
      92           0 :   mValue.mArray = aValue;
      93           0 :   mValue.mArray->AddRef();
      94           0 : }
      95             : 
      96           0 : nsCSSValue::nsCSSValue(mozilla::css::URLValue* aValue)
      97           0 :   : mUnit(eCSSUnit_URL)
      98             : {
      99           0 :   mValue.mURL = aValue;
     100           0 :   mValue.mURL->AddRef();
     101           0 : }
     102             : 
     103           0 : nsCSSValue::nsCSSValue(mozilla::css::ImageValue* aValue)
     104           0 :   : mUnit(eCSSUnit_Image)
     105             : {
     106           0 :   mValue.mImage = aValue;
     107           0 :   mValue.mImage->AddRef();
     108           0 : }
     109             : 
     110           0 : nsCSSValue::nsCSSValue(nsCSSValueGradient* aValue)
     111           0 :   : mUnit(eCSSUnit_Gradient)
     112             : {
     113           0 :   mValue.mGradient = aValue;
     114           0 :   mValue.mGradient->AddRef();
     115           0 : }
     116             : 
     117           0 : nsCSSValue::nsCSSValue(nsCSSValueTokenStream* aValue)
     118           0 :   : mUnit(eCSSUnit_TokenStream)
     119             : {
     120           0 :   mValue.mTokenStream = aValue;
     121           0 :   mValue.mTokenStream->AddRef();
     122           0 : }
     123             : 
     124           0 : nsCSSValue::nsCSSValue(mozilla::css::GridTemplateAreasValue* aValue)
     125           0 :   : mUnit(eCSSUnit_GridTemplateAreas)
     126             : {
     127           0 :   mValue.mGridTemplateAreas = aValue;
     128           0 :   mValue.mGridTemplateAreas->AddRef();
     129           0 : }
     130             : 
     131           0 : nsCSSValue::nsCSSValue(css::FontFamilyListRefCnt* aValue)
     132           0 :   : mUnit(eCSSUnit_FontFamilyList)
     133             : {
     134           0 :   mValue.mFontFamilyList = aValue;
     135           0 :   mValue.mFontFamilyList->AddRef();
     136           0 : }
     137             : 
     138       45268 : nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
     139       45268 :   : mUnit(aCopy.mUnit)
     140             : {
     141       45268 :   if (mUnit <= eCSSUnit_DummyInherit) {
     142             :     // nothing to do, but put this important case first
     143             :   }
     144       38021 :   else if (eCSSUnit_Percent <= mUnit) {
     145       17951 :     mValue.mFloat = aCopy.mValue.mFloat;
     146       17951 :     MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
     147             :   }
     148       20070 :   else if (UnitHasStringValue()) {
     149        2146 :     mValue.mString = aCopy.mValue.mString;
     150        2146 :     mValue.mString->AddRef();
     151             :   }
     152       17924 :   else if (eCSSUnit_Integer <= mUnit && mUnit <= eCSSUnit_EnumColor) {
     153        9874 :     mValue.mInt = aCopy.mValue.mInt;
     154             :   }
     155        8050 :   else if (IsIntegerColorUnit()) {
     156         358 :     mValue.mColor = aCopy.mValue.mColor;
     157             :   }
     158        7692 :   else if (IsFloatColorUnit()) {
     159         461 :     mValue.mFloatColor = aCopy.mValue.mFloatColor;
     160         461 :     mValue.mFloatColor->AddRef();
     161             :   }
     162        7231 :   else if (eCSSUnit_ComplexColor == mUnit) {
     163           0 :     mValue.mComplexColor = aCopy.mValue.mComplexColor;
     164           0 :     mValue.mComplexColor->AddRef();
     165             :   }
     166        7231 :   else if (UnitHasArrayValue()) {
     167         673 :     mValue.mArray = aCopy.mValue.mArray;
     168         673 :     mValue.mArray->AddRef();
     169             :   }
     170        6558 :   else if (eCSSUnit_URL == mUnit) {
     171         765 :     mValue.mURL = aCopy.mValue.mURL;
     172         765 :     mValue.mURL->AddRef();
     173             :   }
     174        5793 :   else if (eCSSUnit_Image == mUnit) {
     175         117 :     mValue.mImage = aCopy.mValue.mImage;
     176         117 :     mValue.mImage->AddRef();
     177             :   }
     178        5676 :   else if (eCSSUnit_Gradient == mUnit) {
     179           5 :     mValue.mGradient = aCopy.mValue.mGradient;
     180           5 :     mValue.mGradient->AddRef();
     181             :   }
     182        5671 :   else if (eCSSUnit_TokenStream == mUnit) {
     183        1489 :     mValue.mTokenStream = aCopy.mValue.mTokenStream;
     184        1489 :     mValue.mTokenStream->AddRef();
     185             :   }
     186        4182 :   else if (eCSSUnit_Pair == mUnit) {
     187         367 :     mValue.mPair = aCopy.mValue.mPair;
     188         367 :     mValue.mPair->AddRef();
     189             :   }
     190        3815 :   else if (eCSSUnit_Triplet == mUnit) {
     191          32 :     mValue.mTriplet = aCopy.mValue.mTriplet;
     192          32 :     mValue.mTriplet->AddRef();
     193             :   }
     194        3783 :   else if (eCSSUnit_Rect == mUnit) {
     195        1002 :     mValue.mRect = aCopy.mValue.mRect;
     196        1002 :     mValue.mRect->AddRef();
     197             :   }
     198        2781 :   else if (eCSSUnit_List == mUnit) {
     199        2342 :     mValue.mList = aCopy.mValue.mList;
     200        2342 :     mValue.mList->AddRef();
     201             :   }
     202         439 :   else if (eCSSUnit_ListDep == mUnit) {
     203           0 :     mValue.mListDependent = aCopy.mValue.mListDependent;
     204             :   }
     205         439 :   else if (eCSSUnit_SharedList == mUnit) {
     206          96 :     mValue.mSharedList = aCopy.mValue.mSharedList;
     207          96 :     mValue.mSharedList->AddRef();
     208             :   }
     209         343 :   else if (eCSSUnit_PairList == mUnit) {
     210         251 :     mValue.mPairList = aCopy.mValue.mPairList;
     211         251 :     mValue.mPairList->AddRef();
     212             :   }
     213          92 :   else if (eCSSUnit_PairListDep == mUnit) {
     214           0 :     mValue.mPairListDependent = aCopy.mValue.mPairListDependent;
     215             :   }
     216          92 :   else if (eCSSUnit_GridTemplateAreas == mUnit) {
     217           0 :     mValue.mGridTemplateAreas = aCopy.mValue.mGridTemplateAreas;
     218           0 :     mValue.mGridTemplateAreas->AddRef();
     219             :   }
     220          92 :   else if (eCSSUnit_FontFamilyList == mUnit) {
     221          16 :     mValue.mFontFamilyList = aCopy.mValue.mFontFamilyList;
     222          16 :     mValue.mFontFamilyList->AddRef();
     223             :   }
     224          76 :   else if (eCSSUnit_AtomIdent == mUnit) {
     225          76 :     mValue.mAtom = aCopy.mValue.mAtom;
     226          76 :     mValue.mAtom->AddRef();
     227             :   }
     228             :   else {
     229           0 :     MOZ_ASSERT(false, "unknown unit");
     230             :   }
     231       45268 : }
     232             : 
     233       42291 : nsCSSValue& nsCSSValue::operator=(const nsCSSValue& aCopy)
     234             : {
     235       42291 :   if (this != &aCopy) {
     236       42291 :     Reset();
     237       42291 :     new (this) nsCSSValue(aCopy);
     238             :   }
     239       42291 :   return *this;
     240             : }
     241             : 
     242             : nsCSSValue&
     243          49 : nsCSSValue::operator=(nsCSSValue&& aOther)
     244             : {
     245          49 :   MOZ_ASSERT(this != &aOther, "Self assigment with rvalue reference");
     246             : 
     247          49 :   Reset();
     248          49 :   mUnit = aOther.mUnit;
     249          49 :   mValue = aOther.mValue;
     250          49 :   aOther.mUnit = eCSSUnit_Null;
     251             : 
     252          49 :   return *this;
     253             : }
     254             : 
     255       14503 : bool nsCSSValue::operator==(const nsCSSValue& aOther) const
     256             : {
     257       14503 :   MOZ_ASSERT(mUnit != eCSSUnit_ListDep &&
     258             :              aOther.mUnit != eCSSUnit_ListDep &&
     259             :              mUnit != eCSSUnit_PairListDep &&
     260             :              aOther.mUnit != eCSSUnit_PairListDep,
     261             :              "don't use operator== with dependent lists");
     262             : 
     263       14503 :   if (mUnit == aOther.mUnit) {
     264        1510 :     if (mUnit <= eCSSUnit_DummyInherit) {
     265          22 :       return true;
     266             :     }
     267        1488 :     else if (UnitHasStringValue()) {
     268           0 :       return (NS_strcmp(GetBufferValue(mValue.mString),
     269           0 :                         GetBufferValue(aOther.mValue.mString)) == 0);
     270             :     }
     271        1488 :     else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_EnumColor)) {
     272          21 :       return mValue.mInt == aOther.mValue.mInt;
     273             :     }
     274        1467 :     else if (IsIntegerColorUnit()) {
     275          48 :       return mValue.mColor == aOther.mValue.mColor;
     276             :     }
     277        1419 :     else if (IsFloatColorUnit()) {
     278           0 :       return *mValue.mFloatColor == *aOther.mValue.mFloatColor;
     279             :     }
     280        1419 :     else if (eCSSUnit_ComplexColor == mUnit) {
     281           0 :       return *mValue.mComplexColor == *aOther.mValue.mComplexColor;
     282             :     }
     283        1419 :     else if (UnitHasArrayValue()) {
     284           0 :       return *mValue.mArray == *aOther.mValue.mArray;
     285             :     }
     286        1419 :     else if (eCSSUnit_URL == mUnit) {
     287           0 :       return mValue.mURL->Equals(*aOther.mValue.mURL);
     288             :     }
     289        1419 :     else if (eCSSUnit_Image == mUnit) {
     290           0 :       return mValue.mImage->Equals(*aOther.mValue.mImage);
     291             :     }
     292        1419 :     else if (eCSSUnit_Gradient == mUnit) {
     293           0 :       return *mValue.mGradient == *aOther.mValue.mGradient;
     294             :     }
     295        1419 :     else if (eCSSUnit_TokenStream == mUnit) {
     296           0 :       return *mValue.mTokenStream == *aOther.mValue.mTokenStream;
     297             :     }
     298        1419 :     else if (eCSSUnit_Pair == mUnit) {
     299           0 :       return *mValue.mPair == *aOther.mValue.mPair;
     300             :     }
     301        1419 :     else if (eCSSUnit_Triplet == mUnit) {
     302           0 :       return *mValue.mTriplet == *aOther.mValue.mTriplet;
     303             :     }
     304        1419 :     else if (eCSSUnit_Rect == mUnit) {
     305           2 :       return *mValue.mRect == *aOther.mValue.mRect;
     306             :     }
     307        1417 :     else if (eCSSUnit_List == mUnit) {
     308           5 :       return nsCSSValueList::Equal(mValue.mList, aOther.mValue.mList);
     309             :     }
     310        1412 :     else if (eCSSUnit_SharedList == mUnit) {
     311           0 :       return *mValue.mSharedList == *aOther.mValue.mSharedList;
     312             :     }
     313        1412 :     else if (eCSSUnit_PairList == mUnit) {
     314           3 :       return nsCSSValuePairList::Equal(mValue.mPairList,
     315           6 :                                        aOther.mValue.mPairList);
     316             :     }
     317        1409 :     else if (eCSSUnit_GridTemplateAreas == mUnit) {
     318           0 :       return *mValue.mGridTemplateAreas == *aOther.mValue.mGridTemplateAreas;
     319             :     }
     320        1409 :     else if (eCSSUnit_FontFamilyList == mUnit) {
     321           0 :       return *mValue.mFontFamilyList == *aOther.mValue.mFontFamilyList;
     322             :     }
     323        1409 :     else if (eCSSUnit_AtomIdent == mUnit) {
     324           0 :       return mValue.mAtom == aOther.mValue.mAtom;
     325             :     }
     326             :     else {
     327        1409 :       return mValue.mFloat == aOther.mValue.mFloat;
     328             :     }
     329             :   }
     330       12993 :   return false;
     331             : }
     332             : 
     333             : double
     334           0 : nsCSSValue::GetAngleValueInRadians() const
     335             : {
     336           0 :   double angle = GetFloatValue();
     337             : 
     338           0 :   switch (GetUnit()) {
     339           0 :     case eCSSUnit_Radian: return angle;
     340           0 :     case eCSSUnit_Turn:   return angle * 2 * M_PI;
     341           0 :     case eCSSUnit_Degree: return angle * M_PI / 180.0;
     342           0 :     case eCSSUnit_Grad:   return angle * M_PI / 200.0;
     343             : 
     344             :     default:
     345           0 :       MOZ_ASSERT(false, "unrecognized angular unit");
     346             :       return 0.0;
     347             :   }
     348             : }
     349             : 
     350             : double
     351           0 : nsCSSValue::GetAngleValueInDegrees() const
     352             : {
     353           0 :   double angle = GetFloatValue();
     354             : 
     355           0 :   switch (GetUnit()) {
     356           0 :     case eCSSUnit_Degree: return angle;
     357           0 :     case eCSSUnit_Grad:   return angle * 0.9; // grad / 400 * 360
     358           0 :     case eCSSUnit_Radian: return angle * 180.0 / M_PI;  // rad / 2pi * 360
     359           0 :     case eCSSUnit_Turn:   return angle * 360.0;
     360             : 
     361             :     default:
     362           0 :       MOZ_ASSERT(false, "unrecognized angular unit");
     363             :       return 0.0;
     364             :   }
     365             : }
     366             : 
     367         242 : imgRequestProxy* nsCSSValue::GetImageValue(nsIDocument* aDocument) const
     368             : {
     369         242 :   MOZ_ASSERT(mUnit == eCSSUnit_Image, "not an Image value");
     370         242 :   return mValue.mImage->mRequests.GetWeak(aDocument);
     371             : }
     372             : 
     373             : already_AddRefed<imgRequestProxy>
     374         141 : nsCSSValue::GetPossiblyStaticImageValue(nsIDocument* aDocument,
     375             :                                         nsPresContext* aPresContext) const
     376             : {
     377         141 :   imgRequestProxy* req = GetImageValue(aDocument);
     378         141 :   if (aPresContext->IsDynamic()) {
     379         141 :     return do_AddRef(req);
     380             :   }
     381           0 :   return nsContentUtils::GetStaticRequest(req);
     382             : }
     383             : 
     384           0 : nscoord nsCSSValue::GetFixedLength(nsPresContext* aPresContext) const
     385             : {
     386           0 :   MOZ_ASSERT(mUnit == eCSSUnit_PhysicalMillimeter,
     387             :              "not a fixed length unit");
     388             : 
     389           0 :   float inches = mValue.mFloat / MM_PER_INCH_FLOAT;
     390           0 :   return NSToCoordFloorClamped(inches *
     391           0 :     float(aPresContext->DeviceContext()->AppUnitsPerPhysicalInch()));
     392             : }
     393             : 
     394        2495 : nscoord nsCSSValue::GetPixelLength() const
     395             : {
     396        2495 :   MOZ_ASSERT(IsPixelLengthUnit(), "not a fixed length unit");
     397             : 
     398             :   double scaleFactor;
     399        2495 :   switch (mUnit) {
     400        2495 :   case eCSSUnit_Pixel: return nsPresContext::CSSPixelsToAppUnits(mValue.mFloat);
     401           0 :   case eCSSUnit_Pica: scaleFactor = 16.0; break;
     402           0 :   case eCSSUnit_Point: scaleFactor = 4/3.0; break;
     403           0 :   case eCSSUnit_Inch: scaleFactor = 96.0; break;
     404           0 :   case eCSSUnit_Millimeter: scaleFactor = 96/25.4; break;
     405           0 :   case eCSSUnit_Centimeter: scaleFactor = 96/2.54; break;
     406           0 :   case eCSSUnit_Quarter: scaleFactor = 96/101.6; break;
     407             :   default:
     408           0 :     NS_ERROR("should never get here");
     409           0 :     return 0;
     410             :   }
     411           0 :   return nsPresContext::CSSPixelsToAppUnits(float(mValue.mFloat*scaleFactor));
     412             : }
     413             : 
     414             : // Assert against resetting non-trivial CSS values from the parallel Servo
     415             : // traversal, since the refcounts aren't thread-safe.
     416             : // Note that the caller might be an OMTA thread, which is allowed to operate off
     417             : // main thread because it owns all of the corresponding nsCSSValues and any that
     418             : // they might be sharing members with.
     419             : #define DO_RELEASE(member) {                                                     \
     420             :   MOZ_ASSERT(NS_IsInCompositorThread() || !ServoStyleSet::IsInServoTraversal()); \
     421             :   mValue.member->Release();                                                      \
     422             : }
     423             : 
     424       44454 : void nsCSSValue::DoReset()
     425             : {
     426       44454 :   if (UnitHasStringValue()) {
     427        2448 :     mValue.mString->Release();
     428       42006 :   } else if (IsFloatColorUnit()) {
     429         522 :     DO_RELEASE(mFloatColor);
     430       41484 :   } else if (eCSSUnit_ComplexColor == mUnit) {
     431           0 :     DO_RELEASE(mComplexColor);
     432       41484 :   } else if (UnitHasArrayValue()) {
     433        1248 :     DO_RELEASE(mArray);
     434       40236 :   } else if (eCSSUnit_URL == mUnit) {
     435         807 :     DO_RELEASE(mURL);
     436       39429 :   } else if (eCSSUnit_Image == mUnit) {
     437         117 :     DO_RELEASE(mImage);
     438       39312 :   } else if (eCSSUnit_Gradient == mUnit) {
     439           8 :     DO_RELEASE(mGradient);
     440       39304 :   } else if (eCSSUnit_TokenStream == mUnit) {
     441        1496 :     DO_RELEASE(mTokenStream);
     442       37808 :   } else if (eCSSUnit_Pair == mUnit) {
     443         456 :     DO_RELEASE(mPair);
     444       37352 :   } else if (eCSSUnit_Triplet == mUnit) {
     445          32 :     DO_RELEASE(mTriplet);
     446       37320 :   } else if (eCSSUnit_Rect == mUnit) {
     447        1272 :     DO_RELEASE(mRect);
     448       36048 :   } else if (eCSSUnit_List == mUnit) {
     449        2927 :     DO_RELEASE(mList);
     450       33121 :   } else if (eCSSUnit_SharedList == mUnit) {
     451          96 :     DO_RELEASE(mSharedList);
     452       33025 :   } else if (eCSSUnit_PairList == mUnit) {
     453         277 :     DO_RELEASE(mPairList);
     454       32748 :   } else if (eCSSUnit_GridTemplateAreas == mUnit) {
     455           0 :     DO_RELEASE(mGridTemplateAreas);
     456       32748 :   } else if (eCSSUnit_FontFamilyList == mUnit) {
     457          16 :     DO_RELEASE(mFontFamilyList);
     458       32732 :   } else if (eCSSUnit_AtomIdent == mUnit) {
     459          76 :     DO_RELEASE(mAtom);
     460             :   }
     461       44454 :   mUnit = eCSSUnit_Null;
     462       44454 : }
     463             : 
     464             : #undef DO_RELEASE
     465             : 
     466        4507 : void nsCSSValue::SetIntValue(int32_t aValue, nsCSSUnit aUnit)
     467             : {
     468        4507 :   MOZ_ASSERT(aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
     469             :              aUnit == eCSSUnit_EnumColor,
     470             :              "not an int value");
     471        4507 :   Reset();
     472        4507 :   if (aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
     473             :       aUnit == eCSSUnit_EnumColor) {
     474        4507 :     mUnit = aUnit;
     475        4507 :     mValue.mInt = aValue;
     476             :   }
     477        4507 : }
     478             : 
     479         321 : void nsCSSValue::SetPercentValue(float aValue)
     480             : {
     481         321 :   Reset();
     482         321 :   mUnit = eCSSUnit_Percent;
     483         321 :   mValue.mFloat = aValue;
     484         321 :   MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
     485         321 : }
     486             : 
     487        5700 : void nsCSSValue::SetFloatValue(float aValue, nsCSSUnit aUnit)
     488             : {
     489        5700 :   MOZ_ASSERT(IsFloatUnit(aUnit), "not a float value");
     490        5700 :   Reset();
     491        5700 :   if (IsFloatUnit(aUnit)) {
     492        5700 :     mUnit = aUnit;
     493        5700 :     mValue.mFloat = aValue;
     494        5700 :     MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
     495             :   }
     496        5700 : }
     497             : 
     498        2291 : void nsCSSValue::SetStringValue(const nsString& aValue,
     499             :                                 nsCSSUnit aUnit)
     500             : {
     501        2291 :   Reset();
     502        2291 :   mUnit = aUnit;
     503        2291 :   MOZ_ASSERT(UnitHasStringValue(), "not a string unit");
     504        2291 :   if (UnitHasStringValue()) {
     505        2291 :     mValue.mString = BufferFromString(aValue).take();
     506             :   } else
     507           0 :     mUnit = eCSSUnit_Null;
     508        2291 : }
     509             : 
     510             : void
     511          76 : nsCSSValue::SetAtomIdentValue(already_AddRefed<nsIAtom> aValue)
     512             : {
     513          76 :   Reset();
     514          76 :   mUnit = eCSSUnit_AtomIdent;
     515          76 :   mValue.mAtom = aValue.take();
     516          76 : }
     517             : 
     518          94 : void nsCSSValue::SetColorValue(nscolor aValue)
     519             : {
     520          94 :   SetIntegerColorValue(aValue, eCSSUnit_RGBAColor);
     521          94 : }
     522             : 
     523             : 
     524             : 
     525         546 : void nsCSSValue::SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit)
     526             : {
     527         546 :   Reset();
     528         546 :   mUnit = aUnit;
     529         546 :   MOZ_ASSERT(IsIntegerColorUnit(), "bad unit");
     530         546 :   mValue.mColor = aValue;
     531         546 : }
     532             : 
     533           0 : void nsCSSValue::SetIntegerCoordValue(nscoord aValue)
     534             : {
     535           0 :   SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(aValue),
     536           0 :                 eCSSUnit_Pixel);
     537           0 : }
     538             : 
     539         171 : void nsCSSValue::SetFloatColorValue(float aComponent1,
     540             :                                     float aComponent2,
     541             :                                     float aComponent3,
     542             :                                     float aAlpha,
     543             :                                     nsCSSUnit aUnit)
     544             : {
     545         171 :   Reset();
     546         171 :   mUnit = aUnit;
     547         171 :   MOZ_ASSERT(IsFloatColorUnit(), "bad unit");
     548         171 :   mValue.mFloatColor =
     549         171 :     new nsCSSValueFloatColor(aComponent1, aComponent2, aComponent3, aAlpha);
     550         171 :   mValue.mFloatColor->AddRef();
     551         171 : }
     552             : 
     553             : void
     554           0 : nsCSSValue::SetRGBAColorValue(const RGBAColorData& aValue)
     555             : {
     556           0 :   SetFloatColorValue(aValue.mR, aValue.mG, aValue.mB,
     557           0 :                      aValue.mA, eCSSUnit_PercentageRGBAColor);
     558           0 : }
     559             : 
     560             : void
     561           0 : nsCSSValue::SetComplexColorValue(already_AddRefed<ComplexColorValue> aValue)
     562             : {
     563           0 :   Reset();
     564           0 :   mUnit = eCSSUnit_ComplexColor;
     565           0 :   mValue.mComplexColor = aValue.take();
     566           0 : }
     567             : 
     568        1038 : void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
     569             : {
     570        1038 :   Reset();
     571        1038 :   mUnit = aUnit;
     572        1038 :   MOZ_ASSERT(UnitHasArrayValue(), "bad unit");
     573        1038 :   mValue.mArray = aValue;
     574        1038 :   mValue.mArray->AddRef();
     575        1038 : }
     576             : 
     577         667 : void nsCSSValue::SetURLValue(mozilla::css::URLValue* aValue)
     578             : {
     579         667 :   Reset();
     580         667 :   mUnit = eCSSUnit_URL;
     581         667 :   mValue.mURL = aValue;
     582         667 :   mValue.mURL->AddRef();
     583         667 : }
     584             : 
     585          40 : void nsCSSValue::SetImageValue(mozilla::css::ImageValue* aValue)
     586             : {
     587          40 :   Reset();
     588          40 :   mUnit = eCSSUnit_Image;
     589          40 :   mValue.mImage = aValue;
     590          40 :   mValue.mImage->AddRef();
     591          40 : }
     592             : 
     593          45 : void nsCSSValue::SetGradientValue(nsCSSValueGradient* aValue)
     594             : {
     595          45 :   Reset();
     596          45 :   mUnit = eCSSUnit_Gradient;
     597          45 :   mValue.mGradient = aValue;
     598          45 :   mValue.mGradient->AddRef();
     599          45 : }
     600             : 
     601         606 : void nsCSSValue::SetTokenStreamValue(nsCSSValueTokenStream* aValue)
     602             : {
     603         606 :   Reset();
     604         606 :   mUnit = eCSSUnit_TokenStream;
     605         606 :   mValue.mTokenStream = aValue;
     606         606 :   mValue.mTokenStream->AddRef();
     607         606 : }
     608             : 
     609           0 : void nsCSSValue::SetGridTemplateAreas(mozilla::css::GridTemplateAreasValue* aValue)
     610             : {
     611           0 :   Reset();
     612           0 :   mUnit = eCSSUnit_GridTemplateAreas;
     613           0 :   mValue.mGridTemplateAreas = aValue;
     614           0 :   mValue.mGridTemplateAreas->AddRef();
     615           0 : }
     616             : 
     617          16 : void nsCSSValue::SetFontFamilyListValue(css::FontFamilyListRefCnt* aValue)
     618             : {
     619          16 :   Reset();
     620          16 :   mUnit = eCSSUnit_FontFamilyList;
     621          16 :   mValue.mFontFamilyList = aValue;
     622          16 :   mValue.mFontFamilyList->AddRef();
     623          16 : }
     624             : 
     625         241 : void nsCSSValue::SetPairValue(const nsCSSValuePair* aValue)
     626             : {
     627             :   // pairs should not be used for null/inherit/initial values
     628         241 :   MOZ_ASSERT(aValue &&
     629             :              aValue->mXValue.GetUnit() != eCSSUnit_Null &&
     630             :              aValue->mYValue.GetUnit() != eCSSUnit_Null &&
     631             :              aValue->mXValue.GetUnit() != eCSSUnit_Inherit &&
     632             :              aValue->mYValue.GetUnit() != eCSSUnit_Inherit &&
     633             :              aValue->mXValue.GetUnit() != eCSSUnit_Initial &&
     634             :              aValue->mYValue.GetUnit() != eCSSUnit_Initial &&
     635             :              aValue->mXValue.GetUnit() != eCSSUnit_Unset &&
     636             :              aValue->mYValue.GetUnit() != eCSSUnit_Unset,
     637             :              "missing or inappropriate pair value");
     638         241 :   Reset();
     639         241 :   mUnit = eCSSUnit_Pair;
     640         241 :   mValue.mPair = new nsCSSValuePair_heap(aValue->mXValue, aValue->mYValue);
     641         241 :   mValue.mPair->AddRef();
     642         241 : }
     643             : 
     644          62 : void nsCSSValue::SetPairValue(const nsCSSValue& xValue,
     645             :                               const nsCSSValue& yValue)
     646             : {
     647          62 :   MOZ_ASSERT(xValue.GetUnit() != eCSSUnit_Null &&
     648             :              yValue.GetUnit() != eCSSUnit_Null &&
     649             :              xValue.GetUnit() != eCSSUnit_Inherit &&
     650             :              yValue.GetUnit() != eCSSUnit_Inherit &&
     651             :              xValue.GetUnit() != eCSSUnit_Initial &&
     652             :              yValue.GetUnit() != eCSSUnit_Initial &&
     653             :              xValue.GetUnit() != eCSSUnit_Unset &&
     654             :              yValue.GetUnit() != eCSSUnit_Unset,
     655             :              "inappropriate pair value");
     656          62 :   Reset();
     657          62 :   mUnit = eCSSUnit_Pair;
     658          62 :   mValue.mPair = new nsCSSValuePair_heap(xValue, yValue);
     659          62 :   mValue.mPair->AddRef();
     660          62 : }
     661             : 
     662           0 : void nsCSSValue::SetTripletValue(const nsCSSValueTriplet* aValue)
     663             : {
     664             :   // triplet should not be used for null/inherit/initial values
     665           0 :   MOZ_ASSERT(aValue &&
     666             :              aValue->mXValue.GetUnit() != eCSSUnit_Null &&
     667             :              aValue->mYValue.GetUnit() != eCSSUnit_Null &&
     668             :              aValue->mZValue.GetUnit() != eCSSUnit_Null &&
     669             :              aValue->mXValue.GetUnit() != eCSSUnit_Inherit &&
     670             :              aValue->mYValue.GetUnit() != eCSSUnit_Inherit &&
     671             :              aValue->mZValue.GetUnit() != eCSSUnit_Inherit &&
     672             :              aValue->mXValue.GetUnit() != eCSSUnit_Initial &&
     673             :              aValue->mYValue.GetUnit() != eCSSUnit_Initial &&
     674             :              aValue->mZValue.GetUnit() != eCSSUnit_Initial &&
     675             :              aValue->mXValue.GetUnit() != eCSSUnit_Unset &&
     676             :              aValue->mYValue.GetUnit() != eCSSUnit_Unset &&
     677             :              aValue->mZValue.GetUnit() != eCSSUnit_Unset,
     678             :              "missing or inappropriate triplet value");
     679           0 :   Reset();
     680           0 :   mUnit = eCSSUnit_Triplet;
     681           0 :   mValue.mTriplet = new nsCSSValueTriplet_heap(aValue->mXValue, aValue->mYValue, aValue->mZValue);
     682           0 :   mValue.mTriplet->AddRef();
     683           0 : }
     684             : 
     685           2 : void nsCSSValue::SetTripletValue(const nsCSSValue& xValue,
     686             :                                  const nsCSSValue& yValue,
     687             :                                  const nsCSSValue& zValue)
     688             : {
     689             :   // Only allow Null for the z component
     690           2 :   MOZ_ASSERT(xValue.GetUnit() != eCSSUnit_Null &&
     691             :              yValue.GetUnit() != eCSSUnit_Null &&
     692             :              xValue.GetUnit() != eCSSUnit_Inherit &&
     693             :              yValue.GetUnit() != eCSSUnit_Inherit &&
     694             :              zValue.GetUnit() != eCSSUnit_Inherit &&
     695             :              xValue.GetUnit() != eCSSUnit_Initial &&
     696             :              yValue.GetUnit() != eCSSUnit_Initial &&
     697             :              zValue.GetUnit() != eCSSUnit_Initial &&
     698             :              xValue.GetUnit() != eCSSUnit_Unset &&
     699             :              yValue.GetUnit() != eCSSUnit_Unset &&
     700             :              zValue.GetUnit() != eCSSUnit_Unset,
     701             :              "inappropriate triplet value");
     702           2 :   Reset();
     703           2 :   mUnit = eCSSUnit_Triplet;
     704           2 :   mValue.mTriplet = new nsCSSValueTriplet_heap(xValue, yValue, zValue);
     705           2 :   mValue.mTriplet->AddRef();
     706           2 : }
     707             : 
     708         806 : nsCSSRect& nsCSSValue::SetRectValue()
     709             : {
     710         806 :   Reset();
     711         806 :   mUnit = eCSSUnit_Rect;
     712         806 :   mValue.mRect = new nsCSSRect_heap;
     713         806 :   mValue.mRect->AddRef();
     714         806 :   return *mValue.mRect;
     715             : }
     716             : 
     717        1870 : nsCSSValueList* nsCSSValue::SetListValue()
     718             : {
     719        1870 :   Reset();
     720        1870 :   mUnit = eCSSUnit_List;
     721        1870 :   mValue.mList = new nsCSSValueList_heap;
     722        1870 :   mValue.mList->AddRef();
     723        1870 :   return mValue.mList;
     724             : }
     725             : 
     726          80 : void nsCSSValue::SetSharedListValue(nsCSSValueSharedList* aList)
     727             : {
     728          80 :   Reset();
     729          80 :   mUnit = eCSSUnit_SharedList;
     730          80 :   mValue.mSharedList = aList;
     731          80 :   mValue.mSharedList->AddRef();
     732          80 : }
     733             : 
     734           0 : void nsCSSValue::SetDependentListValue(nsCSSValueList* aList)
     735             : {
     736           0 :   Reset();
     737           0 :   if (aList) {
     738           0 :     mUnit = eCSSUnit_ListDep;
     739           0 :     mValue.mListDependent = aList;
     740             :   }
     741           0 : }
     742             : 
     743             : void
     744           0 : nsCSSValue::AdoptListValue(UniquePtr<nsCSSValueList> aValue)
     745             : {
     746             :   // We have to copy the first element since for owned lists the first
     747             :   // element should be an nsCSSValueList_heap object.
     748           0 :   SetListValue();
     749           0 :   mValue.mList->mValue = Move(aValue->mValue);
     750           0 :   mValue.mList->mNext  = aValue->mNext;
     751           0 :   aValue->mNext = nullptr;
     752           0 :   aValue.reset();
     753           0 : }
     754             : 
     755         228 : nsCSSValuePairList* nsCSSValue::SetPairListValue()
     756             : {
     757         228 :   Reset();
     758         228 :   mUnit = eCSSUnit_PairList;
     759         228 :   mValue.mPairList = new nsCSSValuePairList_heap;
     760         228 :   mValue.mPairList->AddRef();
     761         228 :   return mValue.mPairList;
     762             : }
     763             : 
     764           0 : void nsCSSValue::SetDependentPairListValue(nsCSSValuePairList* aList)
     765             : {
     766           0 :   Reset();
     767           0 :   if (aList) {
     768           0 :     mUnit = eCSSUnit_PairListDep;
     769           0 :     mValue.mPairListDependent = aList;
     770             :   }
     771           0 : }
     772             : 
     773             : void
     774           0 : nsCSSValue::AdoptPairListValue(UniquePtr<nsCSSValuePairList> aValue)
     775             : {
     776             :   // We have to copy the first element, since for owned pair lists, the first
     777             :   // element should be an nsCSSValuePairList_heap object.
     778           0 :   SetPairListValue();
     779           0 :   mValue.mPairList->mXValue = Move(aValue->mXValue);
     780           0 :   mValue.mPairList->mYValue = Move(aValue->mYValue);
     781           0 :   mValue.mPairList->mNext   = aValue->mNext;
     782           0 :   aValue->mNext = nullptr;
     783           0 :   aValue.reset();
     784           0 : }
     785             : 
     786         211 : void nsCSSValue::SetAutoValue()
     787             : {
     788         211 :   Reset();
     789         211 :   mUnit = eCSSUnit_Auto;
     790         211 : }
     791             : 
     792         434 : void nsCSSValue::SetInheritValue()
     793             : {
     794         434 :   Reset();
     795         434 :   mUnit = eCSSUnit_Inherit;
     796         434 : }
     797             : 
     798          82 : void nsCSSValue::SetInitialValue()
     799             : {
     800          82 :   Reset();
     801          82 :   mUnit = eCSSUnit_Initial;
     802          82 : }
     803             : 
     804          14 : void nsCSSValue::SetUnsetValue()
     805             : {
     806          14 :   Reset();
     807          14 :   mUnit = eCSSUnit_Unset;
     808          14 : }
     809             : 
     810         837 : void nsCSSValue::SetNoneValue()
     811             : {
     812         837 :   Reset();
     813         837 :   mUnit = eCSSUnit_None;
     814         837 : }
     815             : 
     816         106 : void nsCSSValue::SetAllValue()
     817             : {
     818         106 :   Reset();
     819         106 :   mUnit = eCSSUnit_All;
     820         106 : }
     821             : 
     822          32 : void nsCSSValue::SetNormalValue()
     823             : {
     824          32 :   Reset();
     825          32 :   mUnit = eCSSUnit_Normal;
     826          32 : }
     827             : 
     828           0 : void nsCSSValue::SetSystemFontValue()
     829             : {
     830           0 :   Reset();
     831           0 :   mUnit = eCSSUnit_System_Font;
     832           0 : }
     833             : 
     834           0 : void nsCSSValue::SetDummyValue()
     835             : {
     836           0 :   Reset();
     837           0 :   mUnit = eCSSUnit_Dummy;
     838           0 : }
     839             : 
     840           0 : void nsCSSValue::SetDummyInheritValue()
     841             : {
     842           0 :   Reset();
     843           0 :   mUnit = eCSSUnit_DummyInherit;
     844           0 : }
     845             : 
     846           0 : void nsCSSValue::SetCalcValue(const nsStyleCoord::CalcValue* aCalc)
     847             : {
     848           0 :   RefPtr<nsCSSValue::Array> arr = nsCSSValue::Array::Create(1);
     849           0 :   if (!aCalc->mHasPercent) {
     850           0 :     arr->Item(0).SetIntegerCoordValue(aCalc->mLength);
     851             :   } else {
     852           0 :     nsCSSValue::Array *arr2 = nsCSSValue::Array::Create(2);
     853           0 :     arr->Item(0).SetArrayValue(arr2, eCSSUnit_Calc_Plus);
     854           0 :     arr2->Item(0).SetIntegerCoordValue(aCalc->mLength);
     855           0 :     arr2->Item(1).SetPercentValue(aCalc->mPercent);
     856             :   }
     857             : 
     858           0 :   SetArrayValue(arr, eCSSUnit_Calc);
     859           0 : }
     860             : 
     861             : nsStyleCoord::CalcValue
     862           0 : nsCSSValue::GetCalcValue() const
     863             : {
     864           0 :   MOZ_ASSERT(mUnit == eCSSUnit_Calc,
     865             :              "The unit should be eCSSUnit_Calc");
     866             : 
     867           0 :   const nsCSSValue::Array* array = GetArrayValue();
     868           0 :   MOZ_ASSERT(array->Count() == 1,
     869             :              "There should be a 1-length array");
     870             : 
     871           0 :   const nsCSSValue& rootValue = array->Item(0);
     872             : 
     873             :   nsStyleCoord::CalcValue result;
     874             : 
     875           0 :   if (rootValue.GetUnit() == eCSSUnit_Pixel) {
     876           0 :     result.mLength = rootValue.GetFloatValue();
     877           0 :     result.mPercent = 0.0f;
     878           0 :     result.mHasPercent = false;
     879             :   } else {
     880           0 :     MOZ_ASSERT(rootValue.GetUnit() == eCSSUnit_Calc_Plus,
     881             :                "Calc unit should be eCSSUnit_Calc_Plus");
     882             : 
     883           0 :     const nsCSSValue::Array *calcPlusArray = rootValue.GetArrayValue();
     884           0 :     MOZ_ASSERT(calcPlusArray->Count() == 2,
     885             :                "eCSSUnit_Calc_Plus should have a 2-length array");
     886             : 
     887           0 :     const nsCSSValue& length = calcPlusArray->Item(0);
     888           0 :     const nsCSSValue& percent = calcPlusArray->Item(1);
     889           0 :     MOZ_ASSERT(length.GetUnit() == eCSSUnit_Pixel,
     890             :                "The first value should be eCSSUnit_Pixel");
     891           0 :     MOZ_ASSERT(percent.GetUnit() == eCSSUnit_Percent,
     892             :                "The first value should be eCSSUnit_Percent");
     893           0 :     result.mLength = length.GetFloatValue();
     894           0 :     result.mPercent = percent.GetPercentValue();
     895           0 :     result.mHasPercent = true;
     896             :   }
     897             : 
     898           0 :   return result;
     899             : }
     900             : 
     901          40 : void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const
     902             : {
     903          40 :   MOZ_ASSERT(eCSSUnit_URL == mUnit, "Not a URL value!");
     904             :   mozilla::css::ImageValue* image =
     905          40 :     new mozilla::css::ImageValue(mValue.mURL->GetURI(),
     906          40 :                                  mValue.mURL->mString,
     907          80 :                                  do_AddRef(mValue.mURL->mExtraData),
     908         120 :                                  aDocument);
     909             : 
     910          40 :   nsCSSValue* writable = const_cast<nsCSSValue*>(this);
     911          40 :   writable->SetImageValue(image);
     912          40 : }
     913             : 
     914         258 : nscolor nsCSSValue::GetColorValue() const
     915             : {
     916         258 :   MOZ_ASSERT(IsNumericColorUnit(), "not a color value");
     917         258 :   if (IsFloatColorUnit()) {
     918          59 :     return mValue.mFloatColor->GetColorValue(mUnit);
     919             :   }
     920         199 :   return mValue.mColor;
     921             : }
     922             : 
     923           0 : bool nsCSSValue::IsNonTransparentColor() const
     924             : {
     925             :   // We have the value in the form it was specified in at this point, so we
     926             :   // have to look for both the keyword 'transparent' and its equivalent in
     927             :   // rgba notation.
     928           0 :   nsDependentString buf;
     929             :   return
     930           0 :     (IsIntegerColorUnit() && NS_GET_A(GetColorValue()) > 0) ||
     931           0 :     (IsFloatColorUnit() && mValue.mFloatColor->IsNonTransparentColor()) ||
     932           0 :     (mUnit == eCSSUnit_Ident &&
     933           0 :      !nsGkAtoms::transparent->Equals(GetStringValue(buf))) ||
     934           0 :     (mUnit == eCSSUnit_EnumColor);
     935             : }
     936             : 
     937             : nsCSSValue::Array*
     938         141 : nsCSSValue::InitFunction(nsCSSKeyword aFunctionId, uint32_t aNumArgs)
     939             : {
     940         282 :   RefPtr<nsCSSValue::Array> func = Array::Create(aNumArgs + 1);
     941         141 :   func->Item(0).SetIntValue(aFunctionId, eCSSUnit_Enumerated);
     942         141 :   SetArrayValue(func, eCSSUnit_Function);
     943         282 :   return func;
     944             : }
     945             : 
     946             : bool
     947         116 : nsCSSValue::EqualsFunction(nsCSSKeyword aFunctionId) const
     948             : {
     949         116 :   if (mUnit != eCSSUnit_Function) {
     950         110 :     return false;
     951             :   }
     952             : 
     953           6 :   nsCSSValue::Array* func = mValue.mArray;
     954           6 :   MOZ_ASSERT(func && func->Count() >= 1 &&
     955             :              func->Item(0).GetUnit() == eCSSUnit_Enumerated,
     956             :              "illegally structured function value");
     957             : 
     958           6 :   nsCSSKeyword thisFunctionId = func->Item(0).GetKeywordValue();
     959           6 :   return thisFunctionId == aFunctionId;
     960             : }
     961             : 
     962             : // static
     963             : already_AddRefed<nsStringBuffer>
     964        2291 : nsCSSValue::BufferFromString(const nsString& aValue)
     965             : {
     966        4582 :   RefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aValue);
     967        2291 :   if (buffer) {
     968           0 :     return buffer.forget();
     969             :   }
     970             : 
     971        2291 :   nsString::size_type length = aValue.Length();
     972             : 
     973             :   // NOTE: Alloc prouduces a new, already-addref'd (refcnt = 1) buffer.
     974             :   // NOTE: String buffer allocation is currently fallible.
     975        2291 :   size_t sz = (length + 1) * sizeof(char16_t);
     976        2291 :   buffer = nsStringBuffer::Alloc(sz);
     977        2291 :   if (MOZ_UNLIKELY(!buffer)) {
     978           0 :     NS_ABORT_OOM(sz);
     979             :   }
     980             : 
     981        2291 :   char16_t* data = static_cast<char16_t*>(buffer->Data());
     982        2291 :   nsCharTraits<char16_t>::copy(data, aValue.get(), length);
     983             :   // Null-terminate.
     984        2291 :   data[length] = 0;
     985        2291 :   return buffer.forget();
     986             : }
     987             : 
     988             : void
     989          41 : nsCSSValue::AtomizeIdentValue()
     990             : {
     991          41 :   MOZ_ASSERT(mUnit == eCSSUnit_Ident);
     992          82 :   nsCOMPtr<nsIAtom> atom = NS_Atomize(GetStringBufferValue());
     993          41 :   Reset();
     994          41 :   mUnit = eCSSUnit_AtomIdent;
     995          41 :   mValue.mAtom = atom.forget().take();
     996          41 : }
     997             : 
     998             : namespace {
     999             : 
    1000             : struct CSSValueSerializeCalcOps {
    1001           0 :   CSSValueSerializeCalcOps(nsCSSPropertyID aProperty, nsAString& aResult,
    1002             :                            nsCSSValue::Serialization aSerialization)
    1003           0 :     : mProperty(aProperty),
    1004             :       mResult(aResult),
    1005           0 :       mValueSerialization(aSerialization)
    1006             :   {
    1007           0 :   }
    1008             : 
    1009             :   typedef nsCSSValue input_type;
    1010             :   typedef nsCSSValue::Array input_array_type;
    1011             : 
    1012           0 :   static nsCSSUnit GetUnit(const input_type& aValue) {
    1013           0 :     return aValue.GetUnit();
    1014             :   }
    1015             : 
    1016           0 :   void Append(const char* aString)
    1017             :   {
    1018           0 :     mResult.AppendASCII(aString);
    1019           0 :   }
    1020             : 
    1021           0 :   void AppendLeafValue(const input_type& aValue)
    1022             :   {
    1023           0 :     MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Percent ||
    1024             :                aValue.IsLengthUnit() ||
    1025             :                aValue.GetUnit() == eCSSUnit_Number,
    1026             :                "unexpected unit");
    1027           0 :     aValue.AppendToString(mProperty, mResult, mValueSerialization);
    1028           0 :   }
    1029             : 
    1030           0 :   void AppendCoefficient(const input_type& aValue)
    1031             :   {
    1032           0 :     MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Number, "unexpected unit");
    1033           0 :     aValue.AppendToString(mProperty, mResult, mValueSerialization);
    1034           0 :   }
    1035             : 
    1036             : private:
    1037             :   nsCSSPropertyID mProperty;
    1038             :   nsAString &mResult;
    1039             :   nsCSSValue::Serialization mValueSerialization;
    1040             : };
    1041             : 
    1042             : } // namespace
    1043             : 
    1044             : void
    1045           0 : nsCSSValue::AppendPolygonToString(nsCSSPropertyID aProperty, nsAString& aResult,
    1046             :                                   Serialization aSerialization) const
    1047             : {
    1048           0 :   const nsCSSValue::Array* array = GetArrayValue();
    1049           0 :   MOZ_ASSERT(array->Count() > 1 && array->Count() <= 3,
    1050             :              "Polygons must have name and at least one more value.");
    1051             :   // When the array has 2 elements, the item on index 1 is the coordinate
    1052             :   // pair list.
    1053             :   // When the array has 3 elements, the item on index 1 is a fill-rule
    1054             :   // and item on index 2 is the coordinate pair list.
    1055           0 :   size_t index = 1;
    1056           0 :   if (array->Count() == 3) {
    1057           0 :     const nsCSSValue& fillRuleValue = array->Item(index);
    1058           0 :     MOZ_ASSERT(fillRuleValue.GetUnit() == eCSSUnit_Enumerated,
    1059             :                "Expected polygon fill rule.");
    1060           0 :     int32_t fillRule = fillRuleValue.GetIntValue();
    1061           0 :     AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(fillRule,
    1062           0 :                                                   nsCSSProps::kFillRuleKTable),
    1063           0 :                        aResult);
    1064           0 :     aResult.AppendLiteral(", ");
    1065           0 :     ++index;
    1066             :   }
    1067           0 :   array->Item(index).AppendToString(aProperty, aResult, aSerialization);
    1068           0 : }
    1069             : 
    1070             : inline void
    1071           0 : nsCSSValue::AppendPositionCoordinateToString(
    1072             :                 const nsCSSValue& aValue, nsCSSPropertyID aProperty,
    1073             :                 nsAString& aResult, Serialization aSerialization) const
    1074             : {
    1075           0 :   if (aValue.GetUnit() == eCSSUnit_Enumerated) {
    1076           0 :     int32_t intValue = aValue.GetIntValue();
    1077           0 :     AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
    1078           0 :                           nsCSSProps::kShapeRadiusKTable), aResult);
    1079             :   } else {
    1080           0 :     aValue.AppendToString(aProperty, aResult, aSerialization);
    1081             :   }
    1082           0 : }
    1083             : 
    1084             : void
    1085           0 : nsCSSValue::AppendCircleOrEllipseToString(nsCSSKeyword aFunctionId,
    1086             :                                           nsCSSPropertyID aProperty,
    1087             :                                           nsAString& aResult,
    1088             :                                           Serialization aSerialization) const
    1089             : {
    1090           0 :   const nsCSSValue::Array* array = GetArrayValue();
    1091           0 :   size_t count = aFunctionId == eCSSKeyword_circle ? 2 : 3;
    1092           0 :   MOZ_ASSERT(array->Count() == count + 1, "wrong number of arguments");
    1093             : 
    1094           0 :   bool hasRadii = array->Item(1).GetUnit() != eCSSUnit_Null;
    1095             : 
    1096             :   // closest-side is the default, so we don't need to
    1097             :   // output it if all values are closest-side.
    1098           0 :   if (array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
    1099           0 :       StyleShapeRadius(array->Item(1).GetIntValue()) == StyleShapeRadius::ClosestSide &&
    1100           0 :       (aFunctionId == eCSSKeyword_circle ||
    1101           0 :        (array->Item(2).GetUnit() == eCSSUnit_Enumerated &&
    1102           0 :         StyleShapeRadius(array->Item(2).GetIntValue()) == StyleShapeRadius::ClosestSide))) {
    1103           0 :     hasRadii = false;
    1104             :   } else {
    1105           0 :     AppendPositionCoordinateToString(array->Item(1), aProperty,
    1106           0 :                                      aResult, aSerialization);
    1107             : 
    1108           0 :     if (hasRadii && aFunctionId == eCSSKeyword_ellipse) {
    1109           0 :       aResult.Append(' ');
    1110           0 :       AppendPositionCoordinateToString(array->Item(2), aProperty,
    1111           0 :                                        aResult, aSerialization);
    1112             :     }
    1113             :   }
    1114             : 
    1115           0 :   if (hasRadii) {
    1116           0 :     aResult.Append(' ');
    1117             :   }
    1118             : 
    1119             :   // Any position specified?
    1120           0 :   if (array->Item(count).GetUnit() != eCSSUnit_Array) {
    1121           0 :     MOZ_ASSERT(array->Item(count).GetUnit() == eCSSUnit_Null,
    1122             :                "unexpected value");
    1123             :     // We only serialize to the 2 or 4 value form
    1124             :     // |circle()| is valid, but should be expanded
    1125             :     // to |circle(at 50% 50%)|
    1126           0 :     aResult.AppendLiteral("at 50% 50%");
    1127           0 :     return;
    1128             :   }
    1129             : 
    1130           0 :   aResult.AppendLiteral("at ");
    1131           0 :   array->Item(count).AppendBasicShapePositionToString(aResult, aSerialization);
    1132             : }
    1133             : 
    1134             : // https://drafts.csswg.org/css-shapes/#basic-shape-serialization
    1135             : // basic-shape asks us to omit a lot of redundant things whilst serializing
    1136             : // position values. Other specs are not clear about this
    1137             : // (https://github.com/w3c/csswg-drafts/issues/368), so for now we special-case
    1138             : // basic shapes only
    1139             : void
    1140           0 : nsCSSValue::AppendBasicShapePositionToString(nsAString& aResult,
    1141             :                                              Serialization aSerialization) const
    1142             : {
    1143           0 :   const nsCSSValue::Array* array = GetArrayValue();
    1144             :   // We always parse these into an array of four elements
    1145           0 :   MOZ_ASSERT(array->Count() == 4,
    1146             :              "basic-shape position value doesn't have enough elements");
    1147             : 
    1148           0 :   const nsCSSValue &xEdge   = array->Item(0);
    1149           0 :   const nsCSSValue &xOffset = array->Item(1);
    1150           0 :   const nsCSSValue &yEdge   = array->Item(2);
    1151           0 :   const nsCSSValue &yOffset = array->Item(3);
    1152             : 
    1153           0 :   MOZ_ASSERT(xEdge.GetUnit() == eCSSUnit_Enumerated &&
    1154             :              yEdge.GetUnit() == eCSSUnit_Enumerated &&
    1155             :              xOffset.IsLengthPercentCalcUnit() &&
    1156             :              yOffset.IsLengthPercentCalcUnit() &&
    1157             :              xEdge.GetIntValue() != NS_STYLE_IMAGELAYER_POSITION_CENTER &&
    1158             :              yEdge.GetIntValue() != NS_STYLE_IMAGELAYER_POSITION_CENTER,
    1159             :              "Ensure invariants from ParsePositionValueBasicShape "
    1160             :              "haven't been modified");
    1161           0 :   if (xEdge.GetIntValue() == NS_STYLE_IMAGELAYER_POSITION_LEFT &&
    1162           0 :       yEdge.GetIntValue() == NS_STYLE_IMAGELAYER_POSITION_TOP) {
    1163             :     // We can omit these defaults
    1164           0 :     xOffset.AppendToString(eCSSProperty_UNKNOWN, aResult, aSerialization);
    1165           0 :     aResult.Append(' ');
    1166           0 :     yOffset.AppendToString(eCSSProperty_UNKNOWN, aResult, aSerialization);
    1167             :   } else {
    1168             :     // We only serialize to the two or four valued form
    1169           0 :     xEdge.AppendToString(eCSSProperty_object_position, aResult, aSerialization);
    1170           0 :     aResult.Append(' ');
    1171           0 :     xOffset.AppendToString(eCSSProperty_UNKNOWN, aResult, aSerialization);
    1172           0 :     aResult.Append(' ');
    1173           0 :     yEdge.AppendToString(eCSSProperty_object_position, aResult, aSerialization);
    1174           0 :     aResult.Append(' ');
    1175           0 :     yOffset.AppendToString(eCSSProperty_UNKNOWN, aResult, aSerialization);
    1176             :   }
    1177           0 : }
    1178             : 
    1179             : // Helper to append |aString| with the shorthand sides notation used in e.g.
    1180             : // 'padding'. |aProperties| and |aValues| are expected to have 4 elements.
    1181             : /*static*/ void
    1182           0 : nsCSSValue::AppendSidesShorthandToString(const nsCSSPropertyID aProperties[],
    1183             :                                          const nsCSSValue* aValues[],
    1184             :                                          nsAString& aString,
    1185             :                                          nsCSSValue::Serialization
    1186             :                                             aSerialization)
    1187             : {
    1188           0 :   const nsCSSValue& value1 = *aValues[0];
    1189           0 :   const nsCSSValue& value2 = *aValues[1];
    1190           0 :   const nsCSSValue& value3 = *aValues[2];
    1191           0 :   const nsCSSValue& value4 = *aValues[3];
    1192             : 
    1193           0 :   MOZ_ASSERT(value1.GetUnit() != eCSSUnit_Null, "null value 1");
    1194           0 :   value1.AppendToString(aProperties[0], aString, aSerialization);
    1195           0 :   if (value1 != value2 || value1 != value3 || value1 != value4) {
    1196           0 :     aString.Append(char16_t(' '));
    1197           0 :     MOZ_ASSERT(value2.GetUnit() != eCSSUnit_Null, "null value 2");
    1198           0 :     value2.AppendToString(aProperties[1], aString, aSerialization);
    1199           0 :     if (value1 != value3 || value2 != value4) {
    1200           0 :       aString.Append(char16_t(' '));
    1201           0 :       MOZ_ASSERT(value3.GetUnit() != eCSSUnit_Null, "null value 3");
    1202           0 :       value3.AppendToString(aProperties[2], aString, aSerialization);
    1203           0 :       if (value2 != value4) {
    1204           0 :         aString.Append(char16_t(' '));
    1205           0 :         MOZ_ASSERT(value4.GetUnit() != eCSSUnit_Null, "null value 4");
    1206           0 :         value4.AppendToString(aProperties[3], aString, aSerialization);
    1207             :       }
    1208             :     }
    1209             :   }
    1210           0 : }
    1211             : 
    1212             : /*static*/ void
    1213           0 : nsCSSValue::AppendBasicShapeRadiusToString(const nsCSSPropertyID aProperties[],
    1214             :                                            const nsCSSValue* aValues[],
    1215             :                                            nsAString& aResult,
    1216             :                                            Serialization aSerialization)
    1217             : {
    1218           0 :   bool needY = false;
    1219             :   const nsCSSValue* xVals[4];
    1220             :   const nsCSSValue* yVals[4];
    1221           0 :   for (int i = 0; i < 4; i++) {
    1222           0 :     if (aValues[i]->GetUnit() == eCSSUnit_Pair) {
    1223           0 :       needY = true;
    1224           0 :       xVals[i] = &aValues[i]->GetPairValue().mXValue;
    1225           0 :       yVals[i] = &aValues[i]->GetPairValue().mYValue;
    1226             :     } else {
    1227           0 :       xVals[i] = yVals[i] = aValues[i];
    1228             :     }
    1229             :   }
    1230             : 
    1231           0 :   AppendSidesShorthandToString(aProperties, xVals, aResult, aSerialization);
    1232           0 :   if (needY) {
    1233           0 :     aResult.AppendLiteral(" / ");
    1234           0 :     AppendSidesShorthandToString(aProperties, yVals, aResult, aSerialization);
    1235             :   }
    1236           0 : }
    1237             : 
    1238             : void
    1239           0 : nsCSSValue::AppendInsetToString(nsCSSPropertyID aProperty, nsAString& aResult,
    1240             :                                 Serialization aSerialization) const
    1241             : {
    1242           0 :   const nsCSSValue::Array* array = GetArrayValue();
    1243           0 :   MOZ_ASSERT(array->Count() == 6,
    1244             :              "inset function has wrong number of arguments");
    1245           0 :   if (array->Item(1).GetUnit() != eCSSUnit_Null) {
    1246           0 :     array->Item(1).AppendToString(aProperty, aResult, aSerialization);
    1247           0 :     if (array->Item(2).GetUnit() != eCSSUnit_Null) {
    1248           0 :       aResult.Append(' ');
    1249           0 :       array->Item(2).AppendToString(aProperty, aResult, aSerialization);
    1250           0 :       if (array->Item(3).GetUnit() != eCSSUnit_Null) {
    1251           0 :         aResult.Append(' ');
    1252           0 :         array->Item(3).AppendToString(aProperty, aResult, aSerialization);
    1253           0 :         if (array->Item(4).GetUnit() != eCSSUnit_Null) {
    1254           0 :           aResult.Append(' ');
    1255           0 :           array->Item(4).AppendToString(aProperty, aResult, aSerialization);
    1256             :         }
    1257             :       }
    1258             :     }
    1259             :   }
    1260             : 
    1261           0 :   if (array->Item(5).GetUnit() == eCSSUnit_Array) {
    1262             :     const nsCSSPropertyID* subprops =
    1263           0 :       nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius);
    1264           0 :     const nsCSSValue::Array* radius = array->Item(5).GetArrayValue();
    1265           0 :     MOZ_ASSERT(radius->Count() == 4, "expected 4 radii values");
    1266             :     const nsCSSValue* vals[4] = {
    1267           0 :       &(radius->Item(0)),
    1268           0 :       &(radius->Item(1)),
    1269           0 :       &(radius->Item(2)),
    1270           0 :       &(radius->Item(3))
    1271           0 :     };
    1272           0 :     aResult.AppendLiteral(" round ");
    1273             :     AppendBasicShapeRadiusToString(subprops, vals, aResult,
    1274           0 :                                    aSerialization);
    1275             :   } else {
    1276           0 :     MOZ_ASSERT(array->Item(5).GetUnit() == eCSSUnit_Null,
    1277             :                "unexpected value");
    1278             :   }
    1279           0 : }
    1280             : 
    1281             : /* static */ void
    1282           0 : nsCSSValue::AppendAlignJustifyValueToString(int32_t aValue, nsAString& aResult)
    1283             : {
    1284           0 :   auto legacy = aValue & NS_STYLE_ALIGN_LEGACY;
    1285           0 :   if (legacy) {
    1286           0 :     aValue &= ~legacy;
    1287           0 :     aResult.AppendLiteral("legacy ");
    1288             :   }
    1289           0 :   auto overflowPos = aValue & (NS_STYLE_ALIGN_SAFE | NS_STYLE_ALIGN_UNSAFE);
    1290           0 :   aValue &= ~overflowPos;
    1291           0 :   MOZ_ASSERT(!(aValue & NS_STYLE_ALIGN_FLAG_BITS),
    1292             :              "unknown bits in align/justify value");
    1293           0 :   MOZ_ASSERT((aValue != NS_STYLE_ALIGN_AUTO &&
    1294             :               aValue != NS_STYLE_ALIGN_NORMAL &&
    1295             :               aValue != NS_STYLE_ALIGN_BASELINE &&
    1296             :               aValue != NS_STYLE_ALIGN_LAST_BASELINE) ||
    1297             :              (!legacy && !overflowPos),
    1298             :              "auto/normal/baseline/'last baseline' never have any flags");
    1299           0 :   MOZ_ASSERT(legacy == 0 || overflowPos == 0,
    1300             :              "'legacy' together with <overflow-position>");
    1301           0 :   if (aValue == NS_STYLE_ALIGN_LAST_BASELINE) {
    1302           0 :     aResult.AppendLiteral("last ");
    1303           0 :     aValue = NS_STYLE_ALIGN_BASELINE;
    1304             :   }
    1305           0 :   const auto& kwtable(nsCSSProps::kAlignAllKeywords);
    1306           0 :   AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(aValue, kwtable), aResult);
    1307             :   // Don't serialize the 'unsafe' keyword; it's the default.
    1308           0 :   if (MOZ_UNLIKELY(overflowPos == NS_STYLE_ALIGN_SAFE)) {
    1309           0 :     aResult.Append(' ');
    1310           0 :     AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(overflowPos, kwtable),
    1311           0 :                        aResult);
    1312             :   }
    1313           0 : }
    1314             : 
    1315             : void
    1316           0 : nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
    1317             :                            Serialization aSerialization) const
    1318             : {
    1319             :   // eCSSProperty_UNKNOWN gets used for some recursive calls below.
    1320           0 :   MOZ_ASSERT((0 <= aProperty &&
    1321             :               aProperty <= eCSSProperty_COUNT_no_shorthands) ||
    1322             :              aProperty == eCSSProperty_UNKNOWN ||
    1323             :              aProperty == eCSSProperty_DOM,
    1324             :              "property ID out of range");
    1325             : 
    1326           0 :   nsCSSUnit unit = GetUnit();
    1327           0 :   if (unit == eCSSUnit_Null) {
    1328           0 :     return;
    1329             :   }
    1330             : 
    1331           0 :   if (eCSSUnit_String <= unit && unit <= eCSSUnit_Attr) {
    1332           0 :     if (unit == eCSSUnit_Attr) {
    1333           0 :       aResult.AppendLiteral("attr(");
    1334             :     }
    1335           0 :     nsAutoString  buffer;
    1336           0 :     GetStringValue(buffer);
    1337           0 :     if (unit == eCSSUnit_String) {
    1338           0 :       nsStyleUtil::AppendEscapedCSSString(buffer, aResult);
    1339             :     } else {
    1340           0 :       nsStyleUtil::AppendEscapedCSSIdent(buffer, aResult);
    1341           0 :     }
    1342             :   }
    1343           0 :   else if (eCSSUnit_Array <= unit && unit <= eCSSUnit_Symbols) {
    1344           0 :     switch (unit) {
    1345           0 :       case eCSSUnit_Counter:  aResult.AppendLiteral("counter(");  break;
    1346           0 :       case eCSSUnit_Counters: aResult.AppendLiteral("counters("); break;
    1347           0 :       case eCSSUnit_Cubic_Bezier: aResult.AppendLiteral("cubic-bezier("); break;
    1348           0 :       case eCSSUnit_Steps: aResult.AppendLiteral("steps("); break;
    1349           0 :       case eCSSUnit_Symbols: aResult.AppendLiteral("symbols("); break;
    1350           0 :       default: break;
    1351             :     }
    1352             : 
    1353           0 :     nsCSSValue::Array *array = GetArrayValue();
    1354           0 :     bool mark = false;
    1355           0 :     for (size_t i = 0, i_end = array->Count(); i < i_end; ++i) {
    1356           0 :       if (mark && array->Item(i).GetUnit() != eCSSUnit_Null) {
    1357           0 :         if ((unit == eCSSUnit_Array &&
    1358           0 :              eCSSProperty_transition_timing_function != aProperty) ||
    1359             :             unit == eCSSUnit_Symbols)
    1360           0 :           aResult.Append(' ');
    1361           0 :         else if (unit != eCSSUnit_Steps)
    1362           0 :           aResult.AppendLiteral(", ");
    1363             :       }
    1364           0 :       if (unit == eCSSUnit_Steps && i == 1) {
    1365           0 :         MOZ_ASSERT(array->Item(i).GetUnit() == eCSSUnit_Enumerated,
    1366             :                    "unexpected value");
    1367           0 :         int32_t side = array->Item(i).GetIntValue();
    1368           0 :         MOZ_ASSERT(side == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
    1369             :                    side == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END ||
    1370             :                    side == -1,
    1371             :                    "unexpected value");
    1372           0 :         if (side == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START) {
    1373           0 :           aResult.AppendLiteral(", start");
    1374           0 :         } else if (side == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END) {
    1375           0 :           aResult.AppendLiteral(", end");
    1376             :         }
    1377           0 :         continue;
    1378             :       }
    1379           0 :       if (unit == eCSSUnit_Symbols && i == 0) {
    1380           0 :         MOZ_ASSERT(array->Item(i).GetUnit() == eCSSUnit_Enumerated,
    1381             :                    "unexpected value");
    1382           0 :         int32_t system = array->Item(i).GetIntValue();
    1383           0 :         if (system != NS_STYLE_COUNTER_SYSTEM_SYMBOLIC) {
    1384           0 :           AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(
    1385           0 :                   system, nsCSSProps::kCounterSystemKTable), aResult);
    1386           0 :           mark = true;
    1387             :         }
    1388           0 :         continue;
    1389             :       }
    1390             :       nsCSSPropertyID prop =
    1391           0 :         ((eCSSUnit_Counter <= unit && unit <= eCSSUnit_Counters) &&
    1392           0 :          i == array->Count() - 1)
    1393           0 :         ? eCSSProperty_list_style_type : aProperty;
    1394           0 :       if (array->Item(i).GetUnit() != eCSSUnit_Null) {
    1395           0 :         array->Item(i).AppendToString(prop, aResult, aSerialization);
    1396           0 :         mark = true;
    1397             :       }
    1398             :     }
    1399           0 :     if (eCSSUnit_Array == unit &&
    1400             :         aProperty == eCSSProperty_transition_timing_function) {
    1401           0 :       aResult.Append(')');
    1402           0 :     }
    1403             :   }
    1404             :   /* Although Function is backed by an Array, we'll handle it separately
    1405             :    * because it's a bit quirky.
    1406             :    */
    1407           0 :   else if (eCSSUnit_Function == unit) {
    1408           0 :     const nsCSSValue::Array* array = GetArrayValue();
    1409           0 :     MOZ_ASSERT(array->Count() >= 1,
    1410             :                "Functions must have at least one element for the name.");
    1411             : 
    1412           0 :     const nsCSSValue& functionName = array->Item(0);
    1413           0 :     MOZ_ASSERT(functionName.GetUnit() == eCSSUnit_Enumerated,
    1414             :                "Functions must have an enumerated name.");
    1415             :     // The first argument is always of nsCSSKeyword type.
    1416           0 :     const nsCSSKeyword functionId = functionName.GetKeywordValue();
    1417             : 
    1418             :     // minmax(auto, <flex>) is equivalent to (and is our internal representation
    1419             :     // of) <flex>, and both are serialized as <flex>
    1420           0 :     if (functionId == eCSSKeyword_minmax &&
    1421           0 :         array->Count() == 3 &&
    1422           0 :         array->Item(1).GetUnit() == eCSSUnit_Auto &&
    1423           0 :         array->Item(2).GetUnit() == eCSSUnit_FlexFraction) {
    1424           0 :       array->Item(2).AppendToString(aProperty, aResult, aSerialization);
    1425           0 :       MOZ_ASSERT(aProperty == eCSSProperty_grid_template_columns ||
    1426             :                  aProperty == eCSSProperty_grid_template_rows ||
    1427             :                  aProperty == eCSSProperty_grid_auto_columns ||
    1428             :                  aProperty == eCSSProperty_grid_auto_rows);
    1429           0 :       return;
    1430             :     }
    1431             : 
    1432             :     /* Append the function name. */
    1433           0 :     NS_ConvertASCIItoUTF16 ident(nsCSSKeywords::GetStringValue(functionId));
    1434             :     // Bug 721136: Normalize the identifier to lowercase, except that things
    1435             :     // like scaleX should have the last character capitalized.  This matches
    1436             :     // what other browsers do.
    1437           0 :     switch (functionId) {
    1438             :       case eCSSKeyword_rotatex:
    1439             :       case eCSSKeyword_scalex:
    1440             :       case eCSSKeyword_skewx:
    1441             :       case eCSSKeyword_translatex:
    1442           0 :         ident.Replace(ident.Length() - 1, 1, char16_t('X'));
    1443           0 :         break;
    1444             : 
    1445             :       case eCSSKeyword_rotatey:
    1446             :       case eCSSKeyword_scaley:
    1447             :       case eCSSKeyword_skewy:
    1448             :       case eCSSKeyword_translatey:
    1449           0 :         ident.Replace(ident.Length() - 1, 1, char16_t('Y'));
    1450           0 :         break;
    1451             : 
    1452             :       case eCSSKeyword_rotatez:
    1453             :       case eCSSKeyword_scalez:
    1454             :       case eCSSKeyword_translatez:
    1455           0 :         ident.Replace(ident.Length() - 1, 1, char16_t('Z'));
    1456           0 :         break;
    1457             : 
    1458             :       default:
    1459           0 :         break;
    1460             :     }
    1461           0 :     nsStyleUtil::AppendEscapedCSSIdent(ident, aResult);
    1462           0 :     aResult.Append('(');
    1463             : 
    1464           0 :     switch (functionId) {
    1465             :       case eCSSKeyword_polygon:
    1466           0 :         AppendPolygonToString(aProperty, aResult, aSerialization);
    1467           0 :         break;
    1468             : 
    1469             :       case eCSSKeyword_circle:
    1470             :       case eCSSKeyword_ellipse:
    1471           0 :         AppendCircleOrEllipseToString(functionId, aProperty, aResult,
    1472           0 :                                       aSerialization);
    1473           0 :         break;
    1474             : 
    1475             :       case eCSSKeyword_inset:
    1476           0 :         AppendInsetToString(aProperty, aResult, aSerialization);
    1477           0 :         break;
    1478             : 
    1479             :       default: {
    1480             :         // Now, step through the function contents, writing each of
    1481             :         // them as we go.
    1482           0 :         for (size_t index = 1; index < array->Count(); ++index) {
    1483           0 :           array->Item(index).AppendToString(aProperty, aResult,
    1484           0 :                                             aSerialization);
    1485             : 
    1486             :           /* If we're not at the final element, append a comma. */
    1487           0 :           if (index + 1 != array->Count())
    1488           0 :             aResult.AppendLiteral(", ");
    1489             :         }
    1490             :       }
    1491             :     }
    1492             : 
    1493             :     /* Finally, append the closing parenthesis. */
    1494           0 :     aResult.Append(')');
    1495             :   }
    1496           0 :   else if (IsCalcUnit()) {
    1497           0 :     MOZ_ASSERT(GetUnit() == eCSSUnit_Calc, "unexpected unit");
    1498           0 :     CSSValueSerializeCalcOps ops(aProperty, aResult, aSerialization);
    1499           0 :     css::SerializeCalc(*this, ops);
    1500             :   }
    1501           0 :   else if (eCSSUnit_Integer == unit) {
    1502           0 :     aResult.AppendInt(GetIntValue(), 10);
    1503             :   }
    1504           0 :   else if (eCSSUnit_Enumerated == unit) {
    1505           0 :     int32_t intValue = GetIntValue();
    1506           0 :     switch(aProperty) {
    1507             : 
    1508             : 
    1509             :     case eCSSProperty_text_combine_upright:
    1510           0 :       if (intValue <= NS_STYLE_TEXT_COMBINE_UPRIGHT_ALL) {
    1511           0 :         AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue),
    1512           0 :                            aResult);
    1513           0 :       } else if (intValue == NS_STYLE_TEXT_COMBINE_UPRIGHT_DIGITS_2) {
    1514           0 :         aResult.AppendLiteral("digits 2");
    1515           0 :       } else if (intValue == NS_STYLE_TEXT_COMBINE_UPRIGHT_DIGITS_3) {
    1516           0 :         aResult.AppendLiteral("digits 3");
    1517             :       } else {
    1518           0 :         aResult.AppendLiteral("digits 4");
    1519             :       }
    1520           0 :       break;
    1521             : 
    1522             :     case eCSSProperty_text_decoration_line:
    1523           0 :       if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) {
    1524           0 :         AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue),
    1525           0 :                            aResult);
    1526             :       } else {
    1527             :         // Ignore the "override all" internal value.
    1528             :         // (It doesn't have a string representation.)
    1529           0 :         intValue &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
    1530             :         nsStyleUtil::AppendBitmaskCSSValue(
    1531             :           aProperty, intValue,
    1532             :           NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
    1533             :           NS_STYLE_TEXT_DECORATION_LINE_BLINK,
    1534           0 :           aResult);
    1535             :       }
    1536           0 :       break;
    1537             : 
    1538             :     case eCSSProperty_paint_order:
    1539             :       static_assert
    1540             :         (NS_STYLE_PAINT_ORDER_BITWIDTH * NS_STYLE_PAINT_ORDER_LAST_VALUE <= 8,
    1541             :          "SVGStyleStruct::mPaintOrder and the following cast not big enough");
    1542           0 :       nsStyleUtil::AppendPaintOrderValue(static_cast<uint8_t>(GetIntValue()),
    1543           0 :                                          aResult);
    1544           0 :       break;
    1545             : 
    1546             :     case eCSSProperty_font_synthesis:
    1547             :       nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
    1548             :                                          NS_FONT_SYNTHESIS_WEIGHT,
    1549             :                                          NS_FONT_SYNTHESIS_STYLE,
    1550           0 :                                          aResult);
    1551           0 :       break;
    1552             : 
    1553             :     case eCSSProperty_font_variant_east_asian:
    1554             :       nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
    1555             :                                          NS_FONT_VARIANT_EAST_ASIAN_JIS78,
    1556             :                                          NS_FONT_VARIANT_EAST_ASIAN_RUBY,
    1557           0 :                                          aResult);
    1558           0 :       break;
    1559             : 
    1560             :     case eCSSProperty_font_variant_ligatures:
    1561             :       nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
    1562             :                                          NS_FONT_VARIANT_LIGATURES_NONE,
    1563             :                                          NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL,
    1564           0 :                                          aResult);
    1565           0 :       break;
    1566             : 
    1567             :     case eCSSProperty_font_variant_numeric:
    1568             :       nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
    1569             :                                          NS_FONT_VARIANT_NUMERIC_LINING,
    1570             :                                          NS_FONT_VARIANT_NUMERIC_ORDINAL,
    1571           0 :                                          aResult);
    1572           0 :       break;
    1573             : 
    1574             :     case eCSSProperty_grid_auto_flow:
    1575             :       nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
    1576             :                                          NS_STYLE_GRID_AUTO_FLOW_ROW,
    1577             :                                          NS_STYLE_GRID_AUTO_FLOW_DENSE,
    1578           0 :                                          aResult);
    1579           0 :       break;
    1580             : 
    1581             :     case eCSSProperty_grid_column_start:
    1582             :     case eCSSProperty_grid_column_end:
    1583             :     case eCSSProperty_grid_row_start:
    1584             :     case eCSSProperty_grid_row_end:
    1585             :       // "span" is the only enumerated-unit value for these properties
    1586           0 :       aResult.AppendLiteral("span");
    1587           0 :       break;
    1588             : 
    1589             :     case eCSSProperty_touch_action:
    1590             :       nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
    1591             :                                          NS_STYLE_TOUCH_ACTION_NONE,
    1592             :                                          NS_STYLE_TOUCH_ACTION_MANIPULATION,
    1593           0 :                                          aResult);
    1594           0 :       break;
    1595             : 
    1596             :     case eCSSProperty_clip_path:
    1597           0 :       AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
    1598           0 :                             nsCSSProps::kClipPathGeometryBoxKTable),
    1599           0 :                          aResult);
    1600           0 :       break;
    1601             : 
    1602             :     case eCSSProperty_shape_outside:
    1603           0 :       AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
    1604           0 :                             nsCSSProps::kShapeOutsideShapeBoxKTable),
    1605           0 :                          aResult);
    1606           0 :       break;
    1607             : 
    1608             :     case eCSSProperty_contain:
    1609           0 :       if (intValue & NS_STYLE_CONTAIN_STRICT) {
    1610           0 :         NS_ASSERTION(intValue == (NS_STYLE_CONTAIN_STRICT | NS_STYLE_CONTAIN_ALL_BITS),
    1611             :                      "contain: strict should imply contain: layout style paint");
    1612             :         // Only output strict.
    1613           0 :         intValue = NS_STYLE_CONTAIN_STRICT;
    1614             :       }
    1615             :       nsStyleUtil::AppendBitmaskCSSValue(aProperty,
    1616             :                                          intValue,
    1617             :                                          NS_STYLE_CONTAIN_STRICT,
    1618             :                                          NS_STYLE_CONTAIN_PAINT,
    1619           0 :                                          aResult);
    1620           0 :       break;
    1621             : 
    1622             :     case eCSSProperty_align_content:
    1623             :     case eCSSProperty_justify_content: {
    1624           0 :       AppendAlignJustifyValueToString(intValue & NS_STYLE_ALIGN_ALL_BITS, aResult);
    1625           0 :       auto fallback = intValue >> NS_STYLE_ALIGN_ALL_SHIFT;
    1626           0 :       if (fallback) {
    1627           0 :         MOZ_ASSERT(nsCSSProps::ValueToKeywordEnum(fallback & ~NS_STYLE_ALIGN_FLAG_BITS,
    1628             :                                                   nsCSSProps::kAlignSelfPosition)
    1629             :                    != eCSSKeyword_UNKNOWN, "unknown fallback value");
    1630           0 :         aResult.Append(' ');
    1631           0 :         AppendAlignJustifyValueToString(fallback, aResult);
    1632             :       }
    1633           0 :       break;
    1634             :     }
    1635             : 
    1636             :     case eCSSProperty_align_items:
    1637             :     case eCSSProperty_align_self:
    1638             :     case eCSSProperty_justify_items:
    1639             :     case eCSSProperty_justify_self:
    1640           0 :       AppendAlignJustifyValueToString(intValue, aResult);
    1641           0 :       break;
    1642             : 
    1643             :     case eCSSProperty_text_emphasis_position: {
    1644             :       nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
    1645             :                                          NS_STYLE_TEXT_EMPHASIS_POSITION_OVER,
    1646             :                                          NS_STYLE_TEXT_EMPHASIS_POSITION_RIGHT,
    1647           0 :                                          aResult);
    1648           0 :       break;
    1649             :     }
    1650             : 
    1651             :     case eCSSProperty_text_emphasis_style: {
    1652           0 :       auto fill = intValue & NS_STYLE_TEXT_EMPHASIS_STYLE_FILL_MASK;
    1653           0 :       AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(
    1654           0 :         fill, nsCSSProps::kTextEmphasisStyleFillKTable), aResult);
    1655           0 :       aResult.Append(' ');
    1656           0 :       auto shape = intValue & NS_STYLE_TEXT_EMPHASIS_STYLE_SHAPE_MASK;
    1657           0 :       AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(
    1658           0 :         shape, nsCSSProps::kTextEmphasisStyleShapeKTable), aResult);
    1659           0 :       break;
    1660             :     }
    1661             : 
    1662             :     default:
    1663           0 :       const nsCString& name = nsCSSProps::LookupPropertyValue(aProperty, intValue);
    1664           0 :       AppendASCIItoUTF16(name, aResult);
    1665           0 :       break;
    1666             :     }
    1667             :   }
    1668           0 :   else if (eCSSUnit_EnumColor == unit) {
    1669             :     // we can lookup the property in the ColorTable and then
    1670             :     // get a string mapping the name
    1671           0 :     nsAutoCString str;
    1672           0 :     if (nsCSSProps::GetColorName(GetIntValue(), str)){
    1673           0 :       AppendASCIItoUTF16(str, aResult);
    1674             :     } else {
    1675           0 :       MOZ_ASSERT(false, "bad color value");
    1676             :     }
    1677             :   }
    1678           0 :   else if (IsNumericColorUnit(unit)) {
    1679           0 :     if (aSerialization == eNormalized ||
    1680           0 :         unit == eCSSUnit_RGBColor ||
    1681             :         unit == eCSSUnit_RGBAColor) {
    1682           0 :       nscolor color = GetColorValue();
    1683             :       // For brevity, we omit the alpha component if it's equal to 255 (full
    1684             :       // opaque). Also, we use "rgba" rather than "rgb" when the color includes
    1685             :       // the non-opaque alpha value, for backwards-compat (even though they're
    1686             :       // aliases as of css-color-4).
    1687             :       // e.g.:
    1688             :       //   rgba(1, 2, 3, 1.0) => rgb(1, 2, 3)
    1689             :       //   rgba(1, 2, 3, 0.5) => rgba(1, 2, 3, 0.5)
    1690             : 
    1691           0 :       uint8_t a = NS_GET_A(color);
    1692           0 :       bool showAlpha = (a != 255);
    1693             : 
    1694           0 :       if (showAlpha) {
    1695           0 :         aResult.AppendLiteral("rgba(");
    1696             :       } else {
    1697           0 :         aResult.AppendLiteral("rgb(");
    1698             :       }
    1699             : 
    1700           0 :       NS_NAMED_LITERAL_STRING(comma, ", ");
    1701             : 
    1702           0 :       aResult.AppendInt(NS_GET_R(color), 10);
    1703           0 :       aResult.Append(comma);
    1704           0 :       aResult.AppendInt(NS_GET_G(color), 10);
    1705           0 :       aResult.Append(comma);
    1706           0 :       aResult.AppendInt(NS_GET_B(color), 10);
    1707           0 :       if (showAlpha) {
    1708           0 :         aResult.Append(comma);
    1709           0 :         aResult.AppendFloat(nsStyleUtil::ColorComponentToFloat(a));
    1710             :       }
    1711           0 :       aResult.Append(char16_t(')'));
    1712           0 :     } else if (eCSSUnit_HexColor == unit ||
    1713             :                eCSSUnit_HexColorAlpha == unit) {
    1714           0 :       nscolor color = GetColorValue();
    1715           0 :       aResult.Append('#');
    1716           0 :       aResult.AppendPrintf("%02x", NS_GET_R(color));
    1717           0 :       aResult.AppendPrintf("%02x", NS_GET_G(color));
    1718           0 :       aResult.AppendPrintf("%02x", NS_GET_B(color));
    1719           0 :       if (eCSSUnit_HexColorAlpha == unit) {
    1720           0 :         aResult.AppendPrintf("%02x", NS_GET_A(color));
    1721           0 :       }
    1722           0 :     } else if (eCSSUnit_ShortHexColor == unit ||
    1723             :                eCSSUnit_ShortHexColorAlpha == unit) {
    1724           0 :       nscolor color = GetColorValue();
    1725           0 :       aResult.Append('#');
    1726           0 :       aResult.AppendInt(NS_GET_R(color) / 0x11, 16);
    1727           0 :       aResult.AppendInt(NS_GET_G(color) / 0x11, 16);
    1728           0 :       aResult.AppendInt(NS_GET_B(color) / 0x11, 16);
    1729           0 :       if (eCSSUnit_ShortHexColorAlpha == unit) {
    1730           0 :         aResult.AppendInt(NS_GET_A(color) / 0x11, 16);
    1731           0 :       }
    1732             :     } else {
    1733           0 :       MOZ_ASSERT(IsFloatColorUnit());
    1734           0 :       mValue.mFloatColor->AppendToString(unit, aResult);
    1735             :     }
    1736             :   }
    1737           0 :   else if (eCSSUnit_ComplexColor == unit) {
    1738           0 :     StyleComplexColor color = GetStyleComplexColorValue();
    1739           0 :     nsCSSValue serializable;
    1740           0 :     if (color.IsCurrentColor()) {
    1741           0 :       serializable.SetIntValue(NS_COLOR_CURRENTCOLOR, eCSSUnit_EnumColor);
    1742           0 :     } else if (color.IsNumericColor()) {
    1743           0 :       serializable.SetColorValue(color.mColor);
    1744             :     } else {
    1745           0 :       MOZ_ASSERT_UNREACHABLE("Cannot serialize a complex color");
    1746             :     }
    1747           0 :     serializable.AppendToString(aProperty, aResult, aSerialization);
    1748             :   }
    1749           0 :   else if (eCSSUnit_URL == unit || eCSSUnit_Image == unit) {
    1750           0 :     aResult.AppendLiteral("url(");
    1751             :     nsStyleUtil::AppendEscapedCSSString(
    1752           0 :       nsDependentString(GetOriginalURLValue()), aResult);
    1753           0 :     aResult.Append(')');
    1754             :   }
    1755           0 :   else if (eCSSUnit_Element == unit) {
    1756           0 :     aResult.AppendLiteral("-moz-element(#");
    1757           0 :     nsAutoString tmpStr;
    1758           0 :     GetStringValue(tmpStr);
    1759           0 :     nsStyleUtil::AppendEscapedCSSIdent(tmpStr, aResult);
    1760           0 :     aResult.Append(')');
    1761             :   }
    1762           0 :   else if (eCSSUnit_Percent == unit) {
    1763           0 :     aResult.AppendFloat(GetPercentValue() * 100.0f);
    1764             :   }
    1765           0 :   else if (eCSSUnit_Percent < unit) {  // length unit
    1766           0 :     aResult.AppendFloat(GetFloatValue());
    1767             :   }
    1768           0 :   else if (eCSSUnit_Gradient == unit) {
    1769           0 :     nsCSSValueGradient* gradient = GetGradientValue();
    1770             : 
    1771           0 :     if (gradient->mIsLegacySyntax) {
    1772           0 :       if (gradient->mIsMozLegacySyntax) {
    1773           0 :         aResult.AppendLiteral("-moz-");
    1774             :       } else {
    1775           0 :         aResult.AppendLiteral("-webkit-");
    1776             :       }
    1777             :     }
    1778           0 :     if (gradient->mIsRepeating) {
    1779           0 :       aResult.AppendLiteral("repeating-");
    1780             :     }
    1781           0 :     if (gradient->mIsRadial) {
    1782           0 :       aResult.AppendLiteral("radial-gradient(");
    1783             :     } else {
    1784           0 :       aResult.AppendLiteral("linear-gradient(");
    1785             :     }
    1786             : 
    1787           0 :     bool needSep = false;
    1788           0 :     if (gradient->mIsRadial && !gradient->mIsLegacySyntax) {
    1789           0 :       if (!gradient->mIsExplicitSize) {
    1790           0 :         if (gradient->GetRadialShape().GetUnit() != eCSSUnit_None) {
    1791           0 :           MOZ_ASSERT(gradient->GetRadialShape().GetUnit() ==
    1792             :                      eCSSUnit_Enumerated,
    1793             :                      "bad unit for radial gradient shape");
    1794           0 :           int32_t intValue = gradient->GetRadialShape().GetIntValue();
    1795           0 :           MOZ_ASSERT(intValue != NS_STYLE_GRADIENT_SHAPE_LINEAR,
    1796             :                      "radial gradient with linear shape?!");
    1797           0 :           AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
    1798           0 :                                  nsCSSProps::kRadialGradientShapeKTable),
    1799           0 :                              aResult);
    1800           0 :           needSep = true;
    1801             :         }
    1802             : 
    1803           0 :         if (gradient->GetRadialSize().GetUnit() != eCSSUnit_None) {
    1804           0 :           if (needSep) {
    1805           0 :             aResult.Append(' ');
    1806             :           }
    1807           0 :           MOZ_ASSERT(gradient->GetRadialSize().GetUnit() == eCSSUnit_Enumerated,
    1808             :                      "bad unit for radial gradient size");
    1809           0 :           int32_t intValue = gradient->GetRadialSize().GetIntValue();
    1810           0 :           AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
    1811           0 :                                  nsCSSProps::kRadialGradientSizeKTable),
    1812           0 :                              aResult);
    1813           0 :           needSep = true;
    1814             :         }
    1815             :       } else {
    1816           0 :         MOZ_ASSERT(gradient->GetRadiusX().GetUnit() != eCSSUnit_None,
    1817             :                    "bad unit for radial gradient explicit size");
    1818           0 :         gradient->GetRadiusX().AppendToString(aProperty, aResult,
    1819           0 :                                               aSerialization);
    1820           0 :         if (gradient->GetRadiusY().GetUnit() != eCSSUnit_None) {
    1821           0 :           aResult.Append(' ');
    1822           0 :           gradient->GetRadiusY().AppendToString(aProperty, aResult,
    1823           0 :                                                 aSerialization);
    1824             :         }
    1825           0 :         needSep = true;
    1826             :       }
    1827             :     }
    1828           0 :     if (!gradient->mIsRadial &&
    1829           0 :         !(gradient->mIsLegacySyntax && gradient->mIsMozLegacySyntax)) {
    1830           0 :       if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None ||
    1831           0 :           gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None) {
    1832           0 :         MOZ_ASSERT(gradient->mAngle.GetUnit() == eCSSUnit_None);
    1833           0 :         MOZ_ASSERT(gradient->mBgPos.mXValue.GetUnit() == eCSSUnit_Enumerated &&
    1834             :                    gradient->mBgPos.mYValue.GetUnit() == eCSSUnit_Enumerated,
    1835             :                    "unexpected unit");
    1836           0 :         if (!gradient->mIsLegacySyntax) {
    1837           0 :           aResult.AppendLiteral("to ");
    1838             :         }
    1839           0 :         bool didAppendX = false;
    1840           0 :         if (!(gradient->mBgPos.mXValue.GetIntValue() & NS_STYLE_IMAGELAYER_POSITION_CENTER)) {
    1841           0 :           gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position_x,
    1842           0 :                                                   aResult, aSerialization);
    1843           0 :           didAppendX = true;
    1844             :         }
    1845           0 :         if (!(gradient->mBgPos.mYValue.GetIntValue() & NS_STYLE_IMAGELAYER_POSITION_CENTER)) {
    1846           0 :           if (didAppendX) {
    1847             :             // We're appending both an x-keyword and a y-keyword.
    1848             :             // Add a space between them here.
    1849           0 :             aResult.Append(' ');
    1850             :           }
    1851           0 :           gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position_y,
    1852           0 :                                                   aResult, aSerialization);
    1853             :         }
    1854           0 :         needSep = true;
    1855           0 :       } else if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
    1856           0 :         gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
    1857           0 :         needSep = true;
    1858           0 :       }
    1859           0 :     } else if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None ||
    1860           0 :         gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None ||
    1861           0 :         gradient->mAngle.GetUnit() != eCSSUnit_None) {
    1862           0 :       if (needSep) {
    1863           0 :         aResult.Append(' ');
    1864             :       }
    1865           0 :       if (gradient->mIsRadial && !gradient->mIsLegacySyntax) {
    1866           0 :         aResult.AppendLiteral("at ");
    1867             :       }
    1868           0 :       if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None) {
    1869           0 :         gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position_x,
    1870           0 :                                                 aResult, aSerialization);
    1871           0 :         aResult.Append(' ');
    1872             :       }
    1873           0 :       if (gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None) {
    1874           0 :         gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position_y,
    1875           0 :                                                 aResult, aSerialization);
    1876           0 :         aResult.Append(' ');
    1877             :       }
    1878           0 :       if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
    1879           0 :         MOZ_ASSERT(gradient->mIsLegacySyntax,
    1880             :                    "angle is allowed only for legacy syntax");
    1881           0 :         gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
    1882             :       }
    1883           0 :       needSep = true;
    1884             :     }
    1885             : 
    1886           0 :     if (gradient->mIsRadial && gradient->mIsLegacySyntax &&
    1887           0 :         (gradient->GetRadialShape().GetUnit() != eCSSUnit_None ||
    1888           0 :          gradient->GetRadialSize().GetUnit() != eCSSUnit_None)) {
    1889           0 :       MOZ_ASSERT(!gradient->mIsExplicitSize);
    1890           0 :       if (needSep) {
    1891           0 :         aResult.AppendLiteral(", ");
    1892             :       }
    1893           0 :       if (gradient->GetRadialShape().GetUnit() != eCSSUnit_None) {
    1894           0 :         MOZ_ASSERT(gradient->GetRadialShape().GetUnit() == eCSSUnit_Enumerated,
    1895             :                    "bad unit for radial gradient shape");
    1896           0 :         int32_t intValue = gradient->GetRadialShape().GetIntValue();
    1897           0 :         MOZ_ASSERT(intValue != NS_STYLE_GRADIENT_SHAPE_LINEAR,
    1898             :                    "radial gradient with linear shape?!");
    1899           0 :         AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
    1900           0 :                                nsCSSProps::kRadialGradientShapeKTable),
    1901           0 :                            aResult);
    1902           0 :         aResult.Append(' ');
    1903             :       }
    1904             : 
    1905           0 :       if (gradient->GetRadialSize().GetUnit() != eCSSUnit_None) {
    1906           0 :         MOZ_ASSERT(gradient->GetRadialSize().GetUnit() == eCSSUnit_Enumerated,
    1907             :                    "bad unit for radial gradient size");
    1908           0 :         int32_t intValue = gradient->GetRadialSize().GetIntValue();
    1909           0 :         AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
    1910           0 :                                nsCSSProps::kRadialGradientSizeKTable),
    1911           0 :                            aResult);
    1912             :       }
    1913           0 :       needSep = true;
    1914             :     }
    1915           0 :     if (needSep) {
    1916           0 :       aResult.AppendLiteral(", ");
    1917             :     }
    1918             : 
    1919           0 :     for (uint32_t i = 0 ;;) {
    1920           0 :       bool isInterpolationHint = gradient->mStops[i].mIsInterpolationHint;
    1921           0 :       if (!isInterpolationHint) {
    1922           0 :         gradient->mStops[i].mColor.AppendToString(aProperty, aResult,
    1923           0 :                                                   aSerialization);
    1924             :       }
    1925           0 :       if (gradient->mStops[i].mLocation.GetUnit() != eCSSUnit_None) {
    1926           0 :         if (!isInterpolationHint) {
    1927           0 :           aResult.Append(' ');
    1928             :         }
    1929           0 :         gradient->mStops[i].mLocation.AppendToString(aProperty, aResult,
    1930           0 :                                                      aSerialization);
    1931             :       }
    1932           0 :       if (++i == gradient->mStops.Length()) {
    1933           0 :         break;
    1934             :       }
    1935           0 :       aResult.AppendLiteral(", ");
    1936           0 :     }
    1937             : 
    1938           0 :     aResult.Append(')');
    1939           0 :   } else if (eCSSUnit_TokenStream == unit) {
    1940           0 :     nsCSSPropertyID shorthand = mValue.mTokenStream->mShorthandPropertyID;
    1941           0 :     if (shorthand == eCSSProperty_UNKNOWN ||
    1942           0 :         nsCSSProps::PropHasFlags(shorthand, CSS_PROPERTY_IS_ALIAS) ||
    1943             :         aProperty == eCSSProperty__x_system_font) {
    1944             :       // We treat serialization of aliases like '-moz-transform' as a special
    1945             :       // case, since it really wants to be serialized as if it were a longhand
    1946             :       // even though it is implemented as a shorthand. We also need to
    1947             :       // serialize -x-system-font's token stream value, even though the
    1948             :       // value is set through the font shorthand.  This serialization
    1949             :       // of -x-system-font is needed when we need to output the
    1950             :       // 'font' shorthand followed by a number of overriding font
    1951             :       // longhand components.
    1952           0 :       aResult.Append(mValue.mTokenStream->mTokenStream);
    1953             :     }
    1954           0 :   } else if (eCSSUnit_Pair == unit) {
    1955           0 :     if (eCSSProperty_font_variant_alternates == aProperty) {
    1956           0 :       int32_t intValue = GetPairValue().mXValue.GetIntValue();
    1957           0 :       nsAutoString out;
    1958             : 
    1959             :       // simple, enumerated values
    1960           0 :       nsStyleUtil::AppendBitmaskCSSValue(aProperty,
    1961             :           intValue & NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK,
    1962             :           NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
    1963             :           NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
    1964           0 :           out);
    1965             : 
    1966             :       // functional values
    1967           0 :       const nsCSSValueList *list = GetPairValue().mYValue.GetListValue();
    1968           0 :       AutoTArray<gfxAlternateValue,8> altValues;
    1969             : 
    1970           0 :       nsStyleUtil::ComputeFunctionalAlternates(list, altValues);
    1971           0 :       nsStyleUtil::SerializeFunctionalAlternates(altValues, out);
    1972           0 :       aResult.Append(out);
    1973             :     } else {
    1974           0 :       GetPairValue().AppendToString(aProperty, aResult, aSerialization);
    1975             :     }
    1976           0 :   } else if (eCSSUnit_Triplet == unit) {
    1977           0 :     GetTripletValue().AppendToString(aProperty, aResult, aSerialization);
    1978           0 :   } else if (eCSSUnit_Rect == unit) {
    1979           0 :     GetRectValue().AppendToString(aProperty, aResult, aSerialization);
    1980           0 :   } else if (eCSSUnit_List == unit || eCSSUnit_ListDep == unit) {
    1981           0 :     GetListValue()->AppendToString(aProperty, aResult, aSerialization);
    1982           0 :   } else if (eCSSUnit_SharedList == unit) {
    1983           0 :     GetSharedListValue()->AppendToString(aProperty, aResult, aSerialization);
    1984           0 :   } else if (eCSSUnit_PairList == unit || eCSSUnit_PairListDep == unit) {
    1985           0 :     switch (aProperty) {
    1986             :       case eCSSProperty_font_feature_settings:
    1987           0 :         nsStyleUtil::AppendFontFeatureSettings(*this, aResult);
    1988           0 :         break;
    1989             :       default:
    1990           0 :         GetPairListValue()->AppendToString(aProperty, aResult, aSerialization);
    1991           0 :         break;
    1992             :     }
    1993           0 :   } else if (eCSSUnit_GridTemplateAreas == unit) {
    1994           0 :     const mozilla::css::GridTemplateAreasValue* areas = GetGridTemplateAreas();
    1995           0 :     MOZ_ASSERT(!areas->mTemplates.IsEmpty(),
    1996             :                "Unexpected empty array in GridTemplateAreasValue");
    1997           0 :     nsStyleUtil::AppendEscapedCSSString(areas->mTemplates[0], aResult);
    1998           0 :     for (uint32_t i = 1; i < areas->mTemplates.Length(); i++) {
    1999           0 :       aResult.Append(char16_t(' '));
    2000           0 :       nsStyleUtil::AppendEscapedCSSString(areas->mTemplates[i], aResult);
    2001             :     }
    2002           0 :   } else if (eCSSUnit_FontFamilyList == unit) {
    2003           0 :     nsStyleUtil::AppendEscapedCSSFontFamilyList(*mValue.mFontFamilyList,
    2004           0 :                                                 aResult);
    2005           0 :   } else if (eCSSUnit_AtomIdent == unit) {
    2006           0 :     nsDependentAtomString buffer(GetAtomValue());
    2007           0 :     nsStyleUtil::AppendEscapedCSSIdent(buffer, aResult);
    2008             :   }
    2009             : 
    2010           0 :   switch (unit) {
    2011           0 :     case eCSSUnit_Null:         break;
    2012           0 :     case eCSSUnit_Auto:         aResult.AppendLiteral("auto");     break;
    2013           0 :     case eCSSUnit_Inherit:      aResult.AppendLiteral("inherit");  break;
    2014           0 :     case eCSSUnit_Initial:      aResult.AppendLiteral("initial");  break;
    2015           0 :     case eCSSUnit_Unset:        aResult.AppendLiteral("unset");    break;
    2016           0 :     case eCSSUnit_None:         aResult.AppendLiteral("none");     break;
    2017           0 :     case eCSSUnit_Normal:       aResult.AppendLiteral("normal");   break;
    2018           0 :     case eCSSUnit_System_Font:  aResult.AppendLiteral("-moz-use-system-font"); break;
    2019           0 :     case eCSSUnit_All:          aResult.AppendLiteral("all"); break;
    2020             :     case eCSSUnit_Dummy:
    2021             :     case eCSSUnit_DummyInherit:
    2022           0 :       MOZ_ASSERT(false, "should never serialize");
    2023             :       break;
    2024             : 
    2025           0 :     case eCSSUnit_FontFamilyList: break;
    2026           0 :     case eCSSUnit_String:       break;
    2027           0 :     case eCSSUnit_Ident:        break;
    2028           0 :     case eCSSUnit_AtomIdent:    break;
    2029           0 :     case eCSSUnit_URL:          break;
    2030           0 :     case eCSSUnit_Image:        break;
    2031           0 :     case eCSSUnit_Element:      break;
    2032           0 :     case eCSSUnit_Array:        break;
    2033             :     case eCSSUnit_Attr:
    2034             :     case eCSSUnit_Cubic_Bezier:
    2035             :     case eCSSUnit_Steps:
    2036             :     case eCSSUnit_Symbols:
    2037             :     case eCSSUnit_Counter:
    2038           0 :     case eCSSUnit_Counters:     aResult.Append(char16_t(')'));    break;
    2039           0 :     case eCSSUnit_Local_Font:   break;
    2040           0 :     case eCSSUnit_Font_Format:  break;
    2041           0 :     case eCSSUnit_Function:     break;
    2042           0 :     case eCSSUnit_Calc:         break;
    2043           0 :     case eCSSUnit_Calc_Plus:    break;
    2044           0 :     case eCSSUnit_Calc_Minus:   break;
    2045           0 :     case eCSSUnit_Calc_Times_L: break;
    2046           0 :     case eCSSUnit_Calc_Times_R: break;
    2047           0 :     case eCSSUnit_Calc_Divided: break;
    2048           0 :     case eCSSUnit_Integer:      break;
    2049           0 :     case eCSSUnit_Enumerated:   break;
    2050           0 :     case eCSSUnit_EnumColor:             break;
    2051           0 :     case eCSSUnit_RGBColor:              break;
    2052           0 :     case eCSSUnit_RGBAColor:             break;
    2053           0 :     case eCSSUnit_HexColor:              break;
    2054           0 :     case eCSSUnit_ShortHexColor:         break;
    2055           0 :     case eCSSUnit_HexColorAlpha:         break;
    2056           0 :     case eCSSUnit_ShortHexColorAlpha:    break;
    2057           0 :     case eCSSUnit_PercentageRGBColor:    break;
    2058           0 :     case eCSSUnit_PercentageRGBAColor:   break;
    2059           0 :     case eCSSUnit_HSLColor:              break;
    2060           0 :     case eCSSUnit_HSLAColor:             break;
    2061           0 :     case eCSSUnit_ComplexColor:          break;
    2062           0 :     case eCSSUnit_Percent:      aResult.Append(char16_t('%'));    break;
    2063           0 :     case eCSSUnit_Number:       break;
    2064           0 :     case eCSSUnit_Gradient:     break;
    2065           0 :     case eCSSUnit_TokenStream:  break;
    2066           0 :     case eCSSUnit_Pair:         break;
    2067           0 :     case eCSSUnit_Triplet:      break;
    2068           0 :     case eCSSUnit_Rect:         break;
    2069           0 :     case eCSSUnit_List:         break;
    2070           0 :     case eCSSUnit_ListDep:      break;
    2071           0 :     case eCSSUnit_SharedList:   break;
    2072           0 :     case eCSSUnit_PairList:     break;
    2073           0 :     case eCSSUnit_PairListDep:  break;
    2074           0 :     case eCSSUnit_GridTemplateAreas:     break;
    2075             : 
    2076           0 :     case eCSSUnit_Inch:         aResult.AppendLiteral("in");   break;
    2077           0 :     case eCSSUnit_Millimeter:   aResult.AppendLiteral("mm");   break;
    2078           0 :     case eCSSUnit_PhysicalMillimeter: aResult.AppendLiteral("mozmm");   break;
    2079           0 :     case eCSSUnit_Centimeter:   aResult.AppendLiteral("cm");   break;
    2080           0 :     case eCSSUnit_Point:        aResult.AppendLiteral("pt");   break;
    2081           0 :     case eCSSUnit_Pica:         aResult.AppendLiteral("pc");   break;
    2082           0 :     case eCSSUnit_Quarter:      aResult.AppendLiteral("q");    break;
    2083             : 
    2084           0 :     case eCSSUnit_ViewportWidth:  aResult.AppendLiteral("vw");   break;
    2085           0 :     case eCSSUnit_ViewportHeight: aResult.AppendLiteral("vh");   break;
    2086           0 :     case eCSSUnit_ViewportMin:    aResult.AppendLiteral("vmin"); break;
    2087           0 :     case eCSSUnit_ViewportMax:    aResult.AppendLiteral("vmax"); break;
    2088             : 
    2089           0 :     case eCSSUnit_EM:           aResult.AppendLiteral("em");   break;
    2090           0 :     case eCSSUnit_XHeight:      aResult.AppendLiteral("ex");   break;
    2091           0 :     case eCSSUnit_Char:         aResult.AppendLiteral("ch");   break;
    2092           0 :     case eCSSUnit_RootEM:       aResult.AppendLiteral("rem");  break;
    2093             : 
    2094           0 :     case eCSSUnit_Pixel:        aResult.AppendLiteral("px");   break;
    2095             : 
    2096           0 :     case eCSSUnit_Degree:       aResult.AppendLiteral("deg");  break;
    2097           0 :     case eCSSUnit_Grad:         aResult.AppendLiteral("grad"); break;
    2098           0 :     case eCSSUnit_Radian:       aResult.AppendLiteral("rad");  break;
    2099           0 :     case eCSSUnit_Turn:         aResult.AppendLiteral("turn");  break;
    2100             : 
    2101           0 :     case eCSSUnit_Hertz:        aResult.AppendLiteral("Hz");   break;
    2102           0 :     case eCSSUnit_Kilohertz:    aResult.AppendLiteral("kHz");  break;
    2103             : 
    2104           0 :     case eCSSUnit_Seconds:      aResult.Append(char16_t('s'));    break;
    2105           0 :     case eCSSUnit_Milliseconds: aResult.AppendLiteral("ms");   break;
    2106             : 
    2107           0 :     case eCSSUnit_FlexFraction: aResult.AppendLiteral("fr");   break;
    2108             :   }
    2109             : }
    2110             : 
    2111             : size_t
    2112          55 : nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2113             : {
    2114          55 :   size_t n = 0;
    2115             : 
    2116          55 :   switch (GetUnit()) {
    2117             :     // No value: nothing extra to measure.
    2118             :     case eCSSUnit_Null:
    2119             :     case eCSSUnit_Auto:
    2120             :     case eCSSUnit_Inherit:
    2121             :     case eCSSUnit_Initial:
    2122             :     case eCSSUnit_Unset:
    2123             :     case eCSSUnit_None:
    2124             :     case eCSSUnit_Normal:
    2125             :     case eCSSUnit_System_Font:
    2126             :     case eCSSUnit_All:
    2127             :     case eCSSUnit_Dummy:
    2128             :     case eCSSUnit_DummyInherit:
    2129          14 :       break;
    2130             : 
    2131             :     // String
    2132             :     case eCSSUnit_String:
    2133             :     case eCSSUnit_Ident:
    2134             :     case eCSSUnit_Attr:
    2135             :     case eCSSUnit_Local_Font:
    2136             :     case eCSSUnit_Font_Format:
    2137             :     case eCSSUnit_Element:
    2138           2 :       n += mValue.mString->SizeOfIncludingThisIfUnshared(aMallocSizeOf);
    2139           2 :       break;
    2140             : 
    2141             :     // Array
    2142             :     case eCSSUnit_Array:
    2143             :     case eCSSUnit_Counter:
    2144             :     case eCSSUnit_Counters:
    2145             :     case eCSSUnit_Cubic_Bezier:
    2146             :     case eCSSUnit_Steps:
    2147             :     case eCSSUnit_Symbols:
    2148             :     case eCSSUnit_Function:
    2149             :     case eCSSUnit_Calc:
    2150             :     case eCSSUnit_Calc_Plus:
    2151             :     case eCSSUnit_Calc_Minus:
    2152             :     case eCSSUnit_Calc_Times_L:
    2153             :     case eCSSUnit_Calc_Times_R:
    2154             :     case eCSSUnit_Calc_Divided:
    2155           0 :       break;
    2156             : 
    2157             :     // URL
    2158             :     case eCSSUnit_URL:
    2159           0 :       n += mValue.mURL->SizeOfIncludingThis(aMallocSizeOf);
    2160           0 :       break;
    2161             : 
    2162             :     // Image
    2163             :     case eCSSUnit_Image:
    2164             :       // Not yet measured.  Measurement may be added later if DMD finds it
    2165             :       // worthwhile.
    2166           0 :       break;
    2167             : 
    2168             :     // Gradient
    2169             :     case eCSSUnit_Gradient:
    2170           2 :       n += mValue.mGradient->SizeOfIncludingThis(aMallocSizeOf);
    2171           2 :       break;
    2172             : 
    2173             :     // TokenStream
    2174             :     case eCSSUnit_TokenStream:
    2175           0 :       n += mValue.mTokenStream->SizeOfIncludingThis(aMallocSizeOf);
    2176           0 :       break;
    2177             : 
    2178             :     // Pair
    2179             :     case eCSSUnit_Pair:
    2180           0 :       n += mValue.mPair->SizeOfIncludingThis(aMallocSizeOf);
    2181           0 :       break;
    2182             : 
    2183             :     // Triplet
    2184             :     case eCSSUnit_Triplet:
    2185           0 :       n += mValue.mTriplet->SizeOfIncludingThis(aMallocSizeOf);
    2186           0 :       break;
    2187             : 
    2188             :     // Rect
    2189             :     case eCSSUnit_Rect:
    2190           0 :       n += mValue.mRect->SizeOfIncludingThis(aMallocSizeOf);
    2191           0 :       break;
    2192             : 
    2193             :     // List
    2194             :     case eCSSUnit_List:
    2195           2 :       n += mValue.mList->SizeOfIncludingThis(aMallocSizeOf);
    2196           2 :       break;
    2197             : 
    2198             :     // ListDep: not measured because it's non-owning.
    2199             :     case eCSSUnit_ListDep:
    2200           0 :       break;
    2201             : 
    2202             :     // SharedList
    2203             :     case eCSSUnit_SharedList:
    2204             :       // Makes more sense not to measure, since it most cases the list
    2205             :       // will be shared.
    2206           0 :       break;
    2207             : 
    2208             :     // PairList
    2209             :     case eCSSUnit_PairList:
    2210           2 :       n += mValue.mPairList->SizeOfIncludingThis(aMallocSizeOf);
    2211           2 :       break;
    2212             : 
    2213             :     // PairListDep: not measured because it's non-owning.
    2214             :     case eCSSUnit_PairListDep:
    2215           0 :       break;
    2216             : 
    2217             :     // GridTemplateAreas
    2218             :     case eCSSUnit_GridTemplateAreas:
    2219           0 :       n += mValue.mGridTemplateAreas->SizeOfIncludingThis(aMallocSizeOf);
    2220           0 :       break;
    2221             : 
    2222             :     case eCSSUnit_FontFamilyList:
    2223           0 :       n += mValue.mFontFamilyList->SizeOfIncludingThis(aMallocSizeOf);
    2224           0 :       break;
    2225             : 
    2226             :     // Atom is always shared, and thus should not be counted.
    2227             :     case eCSSUnit_AtomIdent:
    2228           0 :       break;
    2229             : 
    2230             :     // Int: nothing extra to measure.
    2231             :     case eCSSUnit_Integer:
    2232             :     case eCSSUnit_Enumerated:
    2233             :     case eCSSUnit_EnumColor:
    2234           8 :       break;
    2235             : 
    2236             :     // Integer Color: nothing extra to measure.
    2237             :     case eCSSUnit_RGBColor:
    2238             :     case eCSSUnit_RGBAColor:
    2239             :     case eCSSUnit_HexColor:
    2240             :     case eCSSUnit_ShortHexColor:
    2241             :     case eCSSUnit_HexColorAlpha:
    2242             :     case eCSSUnit_ShortHexColorAlpha:
    2243           8 :       break;
    2244             : 
    2245             :     // Float Color
    2246             :     case eCSSUnit_PercentageRGBColor:
    2247             :     case eCSSUnit_PercentageRGBAColor:
    2248             :     case eCSSUnit_HSLColor:
    2249             :     case eCSSUnit_HSLAColor:
    2250           4 :       n += mValue.mFloatColor->SizeOfIncludingThis(aMallocSizeOf);
    2251           4 :       break;
    2252             : 
    2253             :     // Complex Color
    2254             :     case eCSSUnit_ComplexColor:
    2255           0 :       n += mValue.mComplexColor->SizeOfIncludingThis(aMallocSizeOf);
    2256           0 :       break;
    2257             : 
    2258             :     // Float: nothing extra to measure.
    2259             :     case eCSSUnit_Percent:
    2260             :     case eCSSUnit_Number:
    2261             :     case eCSSUnit_PhysicalMillimeter:
    2262             :     case eCSSUnit_ViewportWidth:
    2263             :     case eCSSUnit_ViewportHeight:
    2264             :     case eCSSUnit_ViewportMin:
    2265             :     case eCSSUnit_ViewportMax:
    2266             :     case eCSSUnit_EM:
    2267             :     case eCSSUnit_XHeight:
    2268             :     case eCSSUnit_Char:
    2269             :     case eCSSUnit_RootEM:
    2270             :     case eCSSUnit_Point:
    2271             :     case eCSSUnit_Inch:
    2272             :     case eCSSUnit_Millimeter:
    2273             :     case eCSSUnit_Centimeter:
    2274             :     case eCSSUnit_Pica:
    2275             :     case eCSSUnit_Pixel:
    2276             :     case eCSSUnit_Quarter:
    2277             :     case eCSSUnit_Degree:
    2278             :     case eCSSUnit_Grad:
    2279             :     case eCSSUnit_Turn:
    2280             :     case eCSSUnit_Radian:
    2281             :     case eCSSUnit_Hertz:
    2282             :     case eCSSUnit_Kilohertz:
    2283             :     case eCSSUnit_Seconds:
    2284             :     case eCSSUnit_Milliseconds:
    2285             :     case eCSSUnit_FlexFraction:
    2286          13 :       break;
    2287             : 
    2288             :     default:
    2289           0 :       MOZ_ASSERT(false, "bad nsCSSUnit");
    2290             :       break;
    2291             :   }
    2292             : 
    2293          55 :   return n;
    2294             : }
    2295             : 
    2296             : // --- nsCSSValueList -----------------
    2297             : 
    2298        1182 : nsCSSValueList::~nsCSSValueList()
    2299             : {
    2300         591 :   MOZ_COUNT_DTOR(nsCSSValueList);
    2301         596 :   NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, this, mNext);
    2302         591 : }
    2303             : 
    2304             : nsCSSValueList*
    2305           0 : nsCSSValueList::Clone() const
    2306             : {
    2307           0 :   nsCSSValueList* result = new nsCSSValueList(*this);
    2308           0 :   nsCSSValueList* dest = result;
    2309           0 :   const nsCSSValueList* src = this->mNext;
    2310           0 :   while (src) {
    2311           0 :     dest->mNext = new nsCSSValueList(*src);
    2312           0 :     dest = dest->mNext;
    2313           0 :     src = src->mNext;
    2314             :   }
    2315             : 
    2316           0 :   MOZ_ASSERT(result, "shouldn't return null; supposed to be infallible");
    2317           0 :   return result;
    2318             : }
    2319             : 
    2320             : void
    2321           0 : nsCSSValueList::CloneInto(nsCSSValueList* aList) const
    2322             : {
    2323           0 :   NS_ASSERTION(!aList->mNext, "Must be an empty list!");
    2324           0 :   aList->mValue = mValue;
    2325           0 :   aList->mNext = mNext ? mNext->Clone() : nullptr;
    2326           0 : }
    2327             : 
    2328             : static void
    2329           0 : AppendValueListToString(const nsCSSValueList* val,
    2330             :                         nsCSSPropertyID aProperty, nsAString& aResult,
    2331             :                         nsCSSValue::Serialization aSerialization)
    2332             : {
    2333             :   for (;;) {
    2334           0 :     val->mValue.AppendToString(aProperty, aResult, aSerialization);
    2335           0 :     val = val->mNext;
    2336           0 :     if (!val)
    2337           0 :       break;
    2338             : 
    2339           0 :     if (nsCSSProps::PropHasFlags(aProperty,
    2340             :                                  CSS_PROPERTY_VALUE_LIST_USES_COMMAS))
    2341           0 :       aResult.Append(char16_t(','));
    2342           0 :     aResult.Append(char16_t(' '));
    2343             :   }
    2344           0 : }
    2345             : 
    2346             : static void
    2347           0 : AppendGridTemplateToString(const nsCSSValueList* val,
    2348             :                            nsCSSPropertyID aProperty, nsAString& aResult,
    2349             :                            nsCSSValue::Serialization aSerialization)
    2350             : {
    2351             :   // This is called for the "list" that's the top-level value of the property.
    2352           0 :   bool isSubgrid = false;
    2353             :   for (;;) {
    2354           0 :     bool addSpaceSeparator = true;
    2355           0 :     nsCSSUnit unit = val->mValue.GetUnit();
    2356             : 
    2357           0 :     if (unit == eCSSUnit_Enumerated &&
    2358           0 :         val->mValue.GetIntValue() == NS_STYLE_GRID_TEMPLATE_SUBGRID) {
    2359           0 :       MOZ_ASSERT(!isSubgrid, "saw subgrid once already");
    2360           0 :       isSubgrid = true;
    2361           0 :       aResult.AppendLiteral("subgrid");
    2362             : 
    2363           0 :     } else if (unit == eCSSUnit_Pair) {
    2364             :       // This is a repeat 'auto-fill' / 'auto-fit'.
    2365           0 :       const nsCSSValuePair& pair = val->mValue.GetPairValue();
    2366           0 :       switch (pair.mXValue.GetIntValue()) {
    2367             :         case NS_STYLE_GRID_REPEAT_AUTO_FILL:
    2368           0 :           aResult.AppendLiteral("repeat(auto-fill, ");
    2369           0 :           break;
    2370             :         case NS_STYLE_GRID_REPEAT_AUTO_FIT:
    2371           0 :           aResult.AppendLiteral("repeat(auto-fit, ");
    2372           0 :           break;
    2373             :         default:
    2374           0 :           MOZ_ASSERT_UNREACHABLE("unexpected enum value");
    2375             :       }
    2376           0 :       const nsCSSValueList* repeatList = pair.mYValue.GetListValue();
    2377           0 :       if (repeatList->mValue.GetUnit() != eCSSUnit_Null) {
    2378           0 :         aResult.Append('[');
    2379           0 :         AppendValueListToString(repeatList->mValue.GetListValue(), aProperty,
    2380           0 :                                 aResult, aSerialization);
    2381           0 :         aResult.Append(']');
    2382           0 :         if (!isSubgrid) {
    2383           0 :           aResult.Append(' ');
    2384             :         }
    2385           0 :       } else if (isSubgrid) {
    2386           0 :         aResult.AppendLiteral("[]");
    2387             :       }
    2388           0 :       if (!isSubgrid) {
    2389           0 :         repeatList = repeatList->mNext;
    2390           0 :         repeatList->mValue.AppendToString(aProperty, aResult, aSerialization);
    2391           0 :         repeatList = repeatList->mNext;
    2392           0 :         if (repeatList->mValue.GetUnit() != eCSSUnit_Null) {
    2393           0 :           aResult.AppendLiteral(" [");
    2394           0 :           AppendValueListToString(repeatList->mValue.GetListValue(), aProperty,
    2395           0 :                                   aResult, aSerialization);
    2396           0 :           aResult.Append(']');
    2397             :         }
    2398             :       }
    2399           0 :       aResult.Append(')');
    2400             : 
    2401           0 :     } else if (unit == eCSSUnit_Null) {
    2402             :       // Empty or omitted <line-names>.
    2403           0 :       if (isSubgrid) {
    2404           0 :         aResult.AppendLiteral("[]");
    2405             :       } else {
    2406             :         // Serializes to nothing.
    2407           0 :         addSpaceSeparator = false;  // Avoid a double space.
    2408             :       }
    2409             : 
    2410           0 :     } else if (unit == eCSSUnit_List || unit == eCSSUnit_ListDep) {
    2411             :       // Non-empty <line-names>
    2412           0 :       aResult.Append('[');
    2413           0 :       AppendValueListToString(val->mValue.GetListValue(), aProperty,
    2414           0 :                               aResult, aSerialization);
    2415           0 :       aResult.Append(']');
    2416             : 
    2417             :     } else {
    2418             :       // <track-size>
    2419           0 :       val->mValue.AppendToString(aProperty, aResult, aSerialization);
    2420           0 :       if (!isSubgrid &&
    2421           0 :           val->mNext &&
    2422           0 :           val->mNext->mValue.GetUnit() == eCSSUnit_Null &&
    2423           0 :           !val->mNext->mNext) {
    2424             :         // Break out of the loop early to avoid a trailing space.
    2425           0 :         break;
    2426             :       }
    2427             :     }
    2428             : 
    2429           0 :     val = val->mNext;
    2430           0 :     if (!val) {
    2431           0 :       break;
    2432             :     }
    2433             : 
    2434           0 :     if (addSpaceSeparator) {
    2435           0 :       aResult.Append(char16_t(' '));
    2436             :     }
    2437           0 :   }
    2438           0 : }
    2439             : 
    2440             : void
    2441           0 : nsCSSValueList::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
    2442             :                                nsCSSValue::Serialization aSerialization) const
    2443             : {
    2444           0 :   if (aProperty == eCSSProperty_grid_template_columns ||
    2445             :       aProperty == eCSSProperty_grid_template_rows) {
    2446           0 :     AppendGridTemplateToString(this, aProperty, aResult, aSerialization);
    2447             :   } else {
    2448           0 :     AppendValueListToString(this, aProperty, aResult, aSerialization);
    2449             :   }
    2450           0 : }
    2451             : 
    2452             : /* static */ bool
    2453          47 : nsCSSValueList::Equal(const nsCSSValueList* aList1,
    2454             :                       const nsCSSValueList* aList2)
    2455             : {
    2456          47 :   if (aList1 == aList2) {
    2457          42 :     return true;
    2458             :   }
    2459             : 
    2460           5 :   const nsCSSValueList *p1 = aList1, *p2 = aList2;
    2461           7 :   for ( ; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
    2462           5 :     if (p1->mValue != p2->mValue)
    2463           4 :       return false;
    2464             :   }
    2465           1 :   return !p1 && !p2; // true if same length, false otherwise
    2466             : }
    2467             : 
    2468             : size_t
    2469           0 : nsCSSValueList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2470             : {
    2471           0 :   size_t n = 0;
    2472           0 :   const nsCSSValueList* v = this;
    2473           0 :   while (v) {
    2474           0 :     n += aMallocSizeOf(v);
    2475           0 :     n += v->mValue.SizeOfExcludingThis(aMallocSizeOf);
    2476           0 :     v = v->mNext;
    2477             :   }
    2478           0 :   return n;
    2479             : }
    2480             : 
    2481             : size_t
    2482           2 : nsCSSValueList_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2483             : {
    2484             :   // Only measure it if it's unshared, to avoid double-counting.
    2485           2 :   size_t n = 0;
    2486           2 :   if (mRefCnt <= 1) {
    2487           2 :     n += aMallocSizeOf(this);
    2488           2 :     n += mValue.SizeOfExcludingThis(aMallocSizeOf);
    2489           2 :     n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
    2490             :   }
    2491           2 :   return n;
    2492             : }
    2493             : 
    2494             : // --- nsCSSValueSharedList -----------------
    2495             : 
    2496           0 : nsCSSValueSharedList::~nsCSSValueSharedList()
    2497             : {
    2498           0 :   if (mHead) {
    2499           0 :     NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, mHead, mNext);
    2500           0 :     delete mHead;
    2501             :   }
    2502           0 : }
    2503             : 
    2504             : void
    2505           0 : nsCSSValueSharedList::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
    2506             :                                      nsCSSValue::Serialization aSerialization) const
    2507             : {
    2508           0 :   if (mHead) {
    2509           0 :     mHead->AppendToString(aProperty, aResult, aSerialization);
    2510             :   }
    2511           0 : }
    2512             : 
    2513             : bool
    2514           8 : nsCSSValueSharedList::operator==(const nsCSSValueSharedList& aOther) const
    2515             : {
    2516           8 :   return nsCSSValueList::Equal(mHead, aOther.mHead);
    2517             : }
    2518             : 
    2519             : size_t
    2520           0 : nsCSSValueSharedList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2521             : {
    2522             :   // Only measure it if it's unshared, to avoid double-counting.
    2523           0 :   size_t n = 0;
    2524           0 :   if (mRefCnt <= 1) {
    2525           0 :     n += aMallocSizeOf(this);
    2526           0 :     n += mHead->SizeOfIncludingThis(aMallocSizeOf);
    2527             :   }
    2528           0 :   return n;
    2529             : }
    2530             : 
    2531             : // --- nsCSSRect -----------------
    2532             : 
    2533        2701 : nsCSSRect::nsCSSRect(void)
    2534             : {
    2535        2701 :   MOZ_COUNT_CTOR(nsCSSRect);
    2536        2701 : }
    2537             : 
    2538           0 : nsCSSRect::nsCSSRect(const nsCSSRect& aCopy)
    2539             :   : mTop(aCopy.mTop),
    2540             :     mRight(aCopy.mRight),
    2541             :     mBottom(aCopy.mBottom),
    2542           0 :     mLeft(aCopy.mLeft)
    2543             : {
    2544           0 :   MOZ_COUNT_CTOR(nsCSSRect);
    2545           0 : }
    2546             : 
    2547        4334 : nsCSSRect::~nsCSSRect()
    2548             : {
    2549        2167 :   MOZ_COUNT_DTOR(nsCSSRect);
    2550        2167 : }
    2551             : 
    2552             : void
    2553           0 : nsCSSRect::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
    2554             :                           nsCSSValue::Serialization aSerialization) const
    2555             : {
    2556           0 :   MOZ_ASSERT(mTop.GetUnit() != eCSSUnit_Null &&
    2557             :              mTop.GetUnit() != eCSSUnit_Inherit &&
    2558             :              mTop.GetUnit() != eCSSUnit_Initial &&
    2559             :              mTop.GetUnit() != eCSSUnit_Unset,
    2560             :              "parser should have used a bare value");
    2561             : 
    2562           0 :   if (eCSSProperty_border_image_slice == aProperty ||
    2563           0 :       eCSSProperty_border_image_width == aProperty ||
    2564             :       eCSSProperty_border_image_outset == aProperty) {
    2565           0 :     nsCSSPropertyID props[] = { aProperty, aProperty, aProperty, aProperty };
    2566           0 :     const nsCSSValue* values[] = { &mTop, &mRight, &mBottom, &mLeft };
    2567             :     nsCSSValue::AppendSidesShorthandToString(props, values,
    2568           0 :                                              aResult, aSerialization);
    2569           0 :   } else if (eCSSProperty_DOM == aProperty) {
    2570           0 :      NS_NAMED_LITERAL_STRING(space, " ");
    2571             : 
    2572           0 :     mTop.AppendToString(aProperty, aResult, aSerialization);
    2573           0 :     aResult.Append(space);
    2574           0 :     mRight.AppendToString(aProperty, aResult, aSerialization);
    2575           0 :     aResult.Append(space);
    2576           0 :     mBottom.AppendToString(aProperty, aResult, aSerialization);
    2577           0 :     aResult.Append(space);
    2578           0 :     mLeft.AppendToString(aProperty, aResult, aSerialization);
    2579             :   } else {
    2580           0 :     NS_NAMED_LITERAL_STRING(comma, ", ");
    2581             : 
    2582           0 :     aResult.AppendLiteral("rect(");
    2583           0 :     mTop.AppendToString(aProperty, aResult, aSerialization);
    2584           0 :     aResult.Append(comma);
    2585           0 :     mRight.AppendToString(aProperty, aResult, aSerialization);
    2586           0 :     aResult.Append(comma);
    2587           0 :     mBottom.AppendToString(aProperty, aResult, aSerialization);
    2588           0 :     aResult.Append(comma);
    2589           0 :     mLeft.AppendToString(aProperty, aResult, aSerialization);
    2590           0 :     aResult.Append(char16_t(')'));
    2591             :   }
    2592           0 : }
    2593             : 
    2594         723 : void nsCSSRect::SetAllSidesTo(const nsCSSValue& aValue)
    2595             : {
    2596         723 :   mTop = aValue;
    2597         723 :   mRight = aValue;
    2598         723 :   mBottom = aValue;
    2599         723 :   mLeft = aValue;
    2600         723 : }
    2601             : 
    2602             : size_t
    2603           0 : nsCSSRect_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2604             : {
    2605             :   // Only measure it if it's unshared, to avoid double-counting.
    2606           0 :   size_t n = 0;
    2607           0 :   if (mRefCnt <= 1) {
    2608           0 :     n += aMallocSizeOf(this);
    2609           0 :     n += mTop   .SizeOfExcludingThis(aMallocSizeOf);
    2610           0 :     n += mRight .SizeOfExcludingThis(aMallocSizeOf);
    2611           0 :     n += mBottom.SizeOfExcludingThis(aMallocSizeOf);
    2612           0 :     n += mLeft  .SizeOfExcludingThis(aMallocSizeOf);
    2613             :   }
    2614           0 :   return n;
    2615             : }
    2616             : 
    2617             : static_assert(eSideTop == 0 && eSideRight == 1 &&
    2618             :               eSideBottom == 2 && eSideLeft == 3,
    2619             :               "box side constants not top/right/bottom/left == 0/1/2/3");
    2620             : 
    2621             : /* static */ const nsCSSRect::side_type nsCSSRect::sides[4] = {
    2622             :   &nsCSSRect::mTop,
    2623             :   &nsCSSRect::mRight,
    2624             :   &nsCSSRect::mBottom,
    2625             :   &nsCSSRect::mLeft,
    2626             : };
    2627             : 
    2628             : // --- nsCSSValuePair -----------------
    2629             : 
    2630             : void
    2631           0 : nsCSSValuePair::AppendToString(nsCSSPropertyID aProperty,
    2632             :                                nsAString& aResult,
    2633             :                                nsCSSValue::Serialization aSerialization) const
    2634             : {
    2635           0 :   mXValue.AppendToString(aProperty, aResult, aSerialization);
    2636           0 :   if (mYValue.GetUnit() != eCSSUnit_Null) {
    2637           0 :     aResult.Append(char16_t(' '));
    2638           0 :     mYValue.AppendToString(aProperty, aResult, aSerialization);
    2639             :   }
    2640           0 : }
    2641             : 
    2642             : size_t
    2643           2 : nsCSSValuePair::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2644             : {
    2645           2 :   size_t n = 0;
    2646           2 :   n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
    2647           2 :   n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
    2648           2 :   return n;
    2649             : }
    2650             : 
    2651             : size_t
    2652           0 : nsCSSValuePair_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2653             : {
    2654             :   // Only measure it if it's unshared, to avoid double-counting.
    2655           0 :   size_t n = 0;
    2656           0 :   if (mRefCnt <= 1) {
    2657           0 :     n += aMallocSizeOf(this);
    2658           0 :     n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
    2659           0 :     n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
    2660             :   }
    2661           0 :   return n;
    2662             : }
    2663             : 
    2664             : // --- nsCSSValueTriplet -----------------
    2665             : 
    2666             : void
    2667           0 : nsCSSValueTriplet::AppendToString(nsCSSPropertyID aProperty,
    2668             :                                   nsAString& aResult,
    2669             :                                   nsCSSValue::Serialization aSerialization) const
    2670             : {
    2671           0 :   mXValue.AppendToString(aProperty, aResult, aSerialization);
    2672           0 :   if (mYValue.GetUnit() != eCSSUnit_Null) {
    2673           0 :     aResult.Append(char16_t(' '));
    2674           0 :     mYValue.AppendToString(aProperty, aResult, aSerialization);
    2675           0 :     if (mZValue.GetUnit() != eCSSUnit_Null) {
    2676           0 :       aResult.Append(char16_t(' '));
    2677           0 :       mZValue.AppendToString(aProperty, aResult, aSerialization);
    2678             :     }
    2679             :   }
    2680           0 : }
    2681             : 
    2682             : size_t
    2683           0 : nsCSSValueTriplet_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2684             : {
    2685             :   // Only measure it if it's unshared, to avoid double-counting.
    2686           0 :   size_t n = 0;
    2687           0 :   if (mRefCnt <= 1) {
    2688           0 :     n += aMallocSizeOf(this);
    2689           0 :     n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
    2690           0 :     n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
    2691           0 :     n += mZValue.SizeOfExcludingThis(aMallocSizeOf);
    2692             :   }
    2693           0 :   return n;
    2694             : }
    2695             : 
    2696             : // --- nsCSSValuePairList -----------------
    2697             : 
    2698          62 : nsCSSValuePairList::~nsCSSValuePairList()
    2699             : {
    2700          31 :   MOZ_COUNT_DTOR(nsCSSValuePairList);
    2701          36 :   NS_CSS_DELETE_LIST_MEMBER(nsCSSValuePairList, this, mNext);
    2702          31 : }
    2703             : 
    2704             : nsCSSValuePairList*
    2705           0 : nsCSSValuePairList::Clone() const
    2706             : {
    2707           0 :   nsCSSValuePairList* result = new nsCSSValuePairList(*this);
    2708           0 :   nsCSSValuePairList* dest = result;
    2709           0 :   const nsCSSValuePairList* src = this->mNext;
    2710           0 :   while (src) {
    2711           0 :     dest->mNext = new nsCSSValuePairList(*src);
    2712           0 :     dest = dest->mNext;
    2713           0 :     src = src->mNext;
    2714             :   }
    2715             : 
    2716           0 :   MOZ_ASSERT(result, "shouldn't return null; supposed to be infallible");
    2717           0 :   return result;
    2718             : }
    2719             : 
    2720             : void
    2721           0 : nsCSSValuePairList::AppendToString(nsCSSPropertyID aProperty,
    2722             :                                    nsAString& aResult,
    2723             :                                    nsCSSValue::Serialization aSerialization) const
    2724             : {
    2725           0 :   const nsCSSValuePairList* item = this;
    2726           0 :   for (;;) {
    2727           0 :     MOZ_ASSERT(item->mXValue.GetUnit() != eCSSUnit_Null,
    2728             :                "unexpected null unit");
    2729           0 :     item->mXValue.AppendToString(aProperty, aResult, aSerialization);
    2730           0 :     if (item->mXValue.GetUnit() != eCSSUnit_Inherit &&
    2731           0 :         item->mXValue.GetUnit() != eCSSUnit_Initial &&
    2732           0 :         item->mXValue.GetUnit() != eCSSUnit_Unset &&
    2733           0 :         item->mYValue.GetUnit() != eCSSUnit_Null) {
    2734           0 :       aResult.Append(char16_t(' '));
    2735           0 :       item->mYValue.AppendToString(aProperty, aResult, aSerialization);
    2736             :     }
    2737           0 :     item = item->mNext;
    2738           0 :     if (!item)
    2739           0 :       break;
    2740             : 
    2741           0 :     if (nsCSSProps::PropHasFlags(aProperty,
    2742           0 :                                  CSS_PROPERTY_VALUE_LIST_USES_COMMAS) ||
    2743           0 :         aProperty == eCSSProperty_clip_path ||
    2744             :         aProperty == eCSSProperty_shape_outside)
    2745           0 :       aResult.Append(char16_t(','));
    2746           0 :     aResult.Append(char16_t(' '));
    2747             :   }
    2748           0 : }
    2749             : 
    2750             : /* static */ bool
    2751           3 : nsCSSValuePairList::Equal(const nsCSSValuePairList* aList1,
    2752             :                           const nsCSSValuePairList* aList2)
    2753             : {
    2754           3 :   if (aList1 == aList2) {
    2755           0 :     return true;
    2756             :   }
    2757             : 
    2758           3 :   const nsCSSValuePairList *p1 = aList1, *p2 = aList2;
    2759           3 :   for ( ; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
    2760           3 :     if (p1->mXValue != p2->mXValue ||
    2761           0 :         p1->mYValue != p2->mYValue)
    2762           3 :       return false;
    2763             :   }
    2764           0 :   return !p1 && !p2; // true if same length, false otherwise
    2765             : }
    2766             : 
    2767             : size_t
    2768           0 : nsCSSValuePairList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2769             : {
    2770           0 :   size_t n = 0;
    2771           0 :   const nsCSSValuePairList* v = this;
    2772           0 :   while (v) {
    2773           0 :     n += aMallocSizeOf(v);
    2774           0 :     n += v->mXValue.SizeOfExcludingThis(aMallocSizeOf);
    2775           0 :     n += v->mYValue.SizeOfExcludingThis(aMallocSizeOf);
    2776           0 :     v = v->mNext;
    2777             :   }
    2778           0 :   return n;
    2779             : }
    2780             : 
    2781             : size_t
    2782           2 : nsCSSValuePairList_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2783             : {
    2784             :   // Only measure it if it's unshared, to avoid double-counting.
    2785           2 :   size_t n = 0;
    2786           2 :   if (mRefCnt <= 1) {
    2787           2 :     n += aMallocSizeOf(this);
    2788           2 :     n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
    2789           2 :     n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
    2790           2 :     n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
    2791             :   }
    2792           2 :   return n;
    2793             : }
    2794             : 
    2795             : size_t
    2796           0 : nsCSSValue::Array::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2797             : {
    2798           0 :   size_t n = aMallocSizeOf(this);
    2799           0 :   for (size_t i = 0; i < mCount; i++) {
    2800           0 :     n += mArray[i].SizeOfExcludingThis(aMallocSizeOf);
    2801             :   }
    2802           0 :   return n;
    2803             : }
    2804             : 
    2805          40 : css::URLValueData::URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
    2806             :                                 const nsAString& aString,
    2807          40 :                                 already_AddRefed<URLExtraData> aExtraData)
    2808          40 :   : mURI(Move(aURI))
    2809             :   , mString(aString)
    2810          40 :   , mExtraData(Move(aExtraData))
    2811         120 :   , mURIResolved(true)
    2812             : {
    2813          40 :   MOZ_ASSERT(mExtraData);
    2814          40 :   MOZ_ASSERT(mExtraData->GetPrincipal());
    2815          40 : }
    2816             : 
    2817         667 : css::URLValueData::URLValueData(const nsAString& aString,
    2818         667 :                                 already_AddRefed<URLExtraData> aExtraData)
    2819             :   : mString(aString)
    2820         667 :   , mExtraData(Move(aExtraData))
    2821        1334 :   , mURIResolved(false)
    2822             : {
    2823         667 :   MOZ_ASSERT(mExtraData);
    2824         667 :   MOZ_ASSERT(mExtraData->GetPrincipal());
    2825         667 : }
    2826             : 
    2827             : bool
    2828           0 : css::URLValueData::Equals(const URLValueData& aOther) const
    2829             : {
    2830           0 :   MOZ_ASSERT(NS_IsMainThread());
    2831             : 
    2832             :   bool eq;
    2833           0 :   const URLExtraData* self = mExtraData;
    2834           0 :   const URLExtraData* other = aOther.mExtraData;
    2835           0 :   return mString == aOther.mString &&
    2836           0 :           (GetURI() == aOther.GetURI() || // handles null == null
    2837           0 :            (mURI && aOther.mURI &&
    2838           0 :             NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
    2839           0 :             eq)) &&
    2840           0 :           (self->BaseURI() == other->BaseURI() ||
    2841           0 :            (NS_SUCCEEDED(self->BaseURI()->Equals(other->BaseURI(), &eq)) &&
    2842           0 :             eq)) &&
    2843           0 :           (self->GetPrincipal() == other->GetPrincipal() ||
    2844           0 :            self->GetPrincipal()->Equals(other->GetPrincipal())) &&
    2845           0 :           IsLocalRef() == aOther.IsLocalRef();
    2846             : }
    2847             : 
    2848             : bool
    2849          16 : css::URLValueData::DefinitelyEqualURIs(const URLValueData& aOther) const
    2850             : {
    2851          31 :   return mExtraData->BaseURI() == aOther.mExtraData->BaseURI() &&
    2852          31 :          mString == aOther.mString;
    2853             : }
    2854             : 
    2855             : bool
    2856           5 : css::URLValueData::DefinitelyEqualURIsAndPrincipal(
    2857             :     const URLValueData& aOther) const
    2858             : {
    2859          10 :   return mExtraData->GetPrincipal() == aOther.mExtraData->GetPrincipal() &&
    2860          10 :          DefinitelyEqualURIs(aOther);
    2861             : }
    2862             : 
    2863             : nsIURI*
    2864        1514 : css::URLValueData::GetURI() const
    2865             : {
    2866        1514 :   MOZ_ASSERT(NS_IsMainThread());
    2867             : 
    2868        1514 :   if (!mURIResolved) {
    2869         105 :     MOZ_ASSERT(!mURI);
    2870         210 :     nsCOMPtr<nsIURI> newURI;
    2871         315 :     NS_NewURI(getter_AddRefs(newURI),
    2872         210 :               NS_ConvertUTF16toUTF8(mString),
    2873         105 :               nullptr, mExtraData->BaseURI());
    2874         210 :     mURI = new PtrHolder<nsIURI>("URLValueData::mURI", newURI.forget());
    2875         105 :     mURIResolved = true;
    2876             :   }
    2877             : 
    2878        1514 :   return mURI;
    2879             : }
    2880             : 
    2881             : bool
    2882          18 : css::URLValueData::IsLocalRef() const
    2883             : {
    2884          18 :   if (mIsLocalRef.isNothing()) {
    2885             :     // IsLocalRefURL is O(N), use it only when IsLocalRef is called.
    2886           3 :     mIsLocalRef.emplace(nsContentUtils::IsLocalRefURL(mString));
    2887             :   }
    2888             : 
    2889          18 :   return mIsLocalRef.value();
    2890             : }
    2891             : 
    2892             : bool
    2893           0 : css::URLValueData::HasRef() const
    2894             : {
    2895           0 :   if (IsLocalRef()) {
    2896           0 :     return true;
    2897             :   }
    2898             : 
    2899           0 :   nsIURI* uri = GetURI();
    2900           0 :   if (!uri) {
    2901           0 :     return false;
    2902             :   }
    2903             : 
    2904           0 :   nsAutoCString ref;
    2905           0 :   nsresult rv = uri->GetRef(ref);
    2906           0 :   if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
    2907           0 :     return true;
    2908             :   }
    2909             : 
    2910           0 :   return false;
    2911             : }
    2912             : 
    2913             : bool
    2914           2 : css::URLValueData::MightHaveRef() const
    2915             : {
    2916           2 :   if (mMightHaveRef.isNothing()) {
    2917             :     // ::MightHaveRef is O(N), use it only use it only when MightHaveRef is
    2918             :     // called.
    2919           1 :     mMightHaveRef.emplace(::MightHaveRef(mString));
    2920             :   }
    2921             : 
    2922           2 :   return mMightHaveRef.value();
    2923             : }
    2924             : 
    2925             : already_AddRefed<nsIURI>
    2926           8 : css::URLValueData::ResolveLocalRef(nsIURI* aURI) const
    2927             : {
    2928          16 :   nsCOMPtr<nsIURI> result = GetURI();
    2929             : 
    2930           8 :   if (result && IsLocalRef()) {
    2931          16 :     nsCString ref;
    2932           8 :     mURI->GetRef(ref);
    2933             : 
    2934           8 :     aURI->Clone(getter_AddRefs(result));
    2935           8 :     result->SetRef(ref);
    2936             :   }
    2937             : 
    2938          16 :   return result.forget();
    2939             : }
    2940             : 
    2941             : already_AddRefed<nsIURI>
    2942           0 : css::URLValueData::ResolveLocalRef(nsIContent* aContent) const
    2943             : {
    2944           0 :   nsCOMPtr<nsIURI> url = aContent->GetBaseURI();
    2945           0 :   return ResolveLocalRef(url);
    2946             : }
    2947             : 
    2948             : void
    2949           0 : css::URLValueData::GetSourceString(nsString& aRef) const
    2950             : {
    2951           0 :   nsIURI* uri = GetURI();
    2952           0 :   if (!uri) {
    2953           0 :     aRef.Truncate();
    2954           0 :     return;
    2955             :   }
    2956             : 
    2957           0 :   nsCString cref;
    2958           0 :   if (IsLocalRef()) {
    2959             :     // XXXheycam It's possible we can just return mString in this case, since
    2960             :     // it should be the "#fragment" string the URLValueData was created with.
    2961           0 :     uri->GetRef(cref);
    2962           0 :     cref.Insert('#', 0);
    2963             :   } else {
    2964             :     // It's not entirely clear how to best handle failure here. Ensuring the
    2965             :     // string is empty seems safest.
    2966           0 :     nsresult rv = uri->GetSpec(cref);
    2967           0 :     if (NS_FAILED(rv)) {
    2968           0 :       cref.Truncate();
    2969             :     }
    2970             :   }
    2971             : 
    2972           0 :   aRef = NS_ConvertUTF8toUTF16(cref);
    2973             : }
    2974             : 
    2975             : bool
    2976           0 : css::URLValueData::EqualsExceptRef(nsIURI* aURI) const
    2977             : {
    2978           0 :   nsIURI* uri = GetURI();
    2979           0 :   if (!uri) {
    2980           0 :     return false;
    2981             :   }
    2982             : 
    2983           0 :   bool ret = false;
    2984           0 :   uri->EqualsExceptRef(aURI, &ret);
    2985           0 :   return ret;
    2986             : }
    2987             : 
    2988             : size_t
    2989           0 : css::URLValueData::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    2990             : {
    2991           0 :   size_t n = 0;
    2992           0 :   n += mString.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
    2993             : 
    2994             :   // Measurement of the following members may be added later if DMD finds it
    2995             :   // is worthwhile:
    2996             :   // - mURI
    2997             :   // - mExtraData
    2998           0 :   return n;
    2999             : }
    3000             : 
    3001         667 : URLValue::URLValue(const nsAString& aString, nsIURI* aBaseURI, nsIURI* aReferrer,
    3002         667 :                    nsIPrincipal* aOriginPrincipal)
    3003        1334 :   : URLValueData(aString, do_AddRef(new URLExtraData(aBaseURI, aReferrer,
    3004        2001 :                                                      aOriginPrincipal)))
    3005             : {
    3006         667 :   MOZ_ASSERT(NS_IsMainThread());
    3007         667 : }
    3008             : 
    3009           0 : URLValue::URLValue(nsIURI* aURI, const nsAString& aString, nsIURI* aBaseURI,
    3010           0 :                    nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
    3011           0 :   : URLValueData(do_AddRef(new PtrHolder<nsIURI>("URLValueData::mURI", aURI)),
    3012             :                  aString,
    3013           0 :                  do_AddRef(new URLExtraData(aBaseURI, aReferrer,
    3014           0 :                                             aOriginPrincipal)))
    3015             : {
    3016           0 :   MOZ_ASSERT(NS_IsMainThread());
    3017           0 : }
    3018             : 
    3019             : size_t
    3020           0 : css::URLValue::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    3021             : {
    3022             :   // Only measure it if it's unshared, to avoid double-counting.
    3023           0 :   size_t n = 0;
    3024           0 :   if (mRefCnt <= 1) {
    3025           0 :     n += aMallocSizeOf(this);
    3026           0 :     n += URLValueData::SizeOfExcludingThis(aMallocSizeOf);
    3027             :   }
    3028           0 :   return n;
    3029             : }
    3030             : 
    3031          40 : css::ImageValue::ImageValue(nsIURI* aURI, const nsAString& aString,
    3032             :                             already_AddRefed<URLExtraData> aExtraData,
    3033          40 :                             nsIDocument* aDocument)
    3034          80 :   : URLValueData(do_AddRef(new PtrHolder<nsIURI>("URLValueData::mURI", aURI)),
    3035         120 :                  aString, Move(aExtraData))
    3036             : {
    3037          40 :   Initialize(aDocument);
    3038          40 : }
    3039             : 
    3040           0 : css::ImageValue::ImageValue(const nsAString& aString,
    3041           0 :                             already_AddRefed<URLExtraData> aExtraData)
    3042           0 :   : URLValueData(aString, Move(aExtraData))
    3043             : {
    3044           0 : }
    3045             : 
    3046             : void
    3047          40 : css::ImageValue::Initialize(nsIDocument* aDocument)
    3048             : {
    3049          40 :   MOZ_ASSERT(NS_IsMainThread());
    3050             : 
    3051             :   // NB: If aDocument is not the original document, we may not be able to load
    3052             :   // images from aDocument.  Instead we do the image load from the original doc
    3053             :   // and clone it to aDocument.
    3054          40 :   nsIDocument* loadingDoc = aDocument->GetOriginalDocument();
    3055          40 :   if (!loadingDoc) {
    3056          40 :     loadingDoc = aDocument;
    3057             :   }
    3058             : 
    3059          40 :   if (!mLoadedImage) {
    3060          40 :     loadingDoc->StyleImageLoader()->LoadImage(GetURI(),
    3061             :                                               mExtraData->GetPrincipal(),
    3062          40 :                                               mExtraData->GetReferrer(), this);
    3063             : 
    3064          40 :      mLoadedImage = true;
    3065             :   }
    3066             : 
    3067          40 :   aDocument->StyleImageLoader()->MaybeRegisterCSSImage(this);
    3068          40 : }
    3069             : 
    3070           0 : css::ImageValue::~ImageValue()
    3071             : {
    3072           0 :   MOZ_ASSERT(NS_IsMainThread() || mRequests.Count() == 0,
    3073             :              "Destructor should run on main thread, or on non-main thread "
    3074             :              "when mRequest is empty!");
    3075             : 
    3076           0 :   for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) {
    3077           0 :     nsIDocument* doc = iter.Key();
    3078           0 :     RefPtr<imgRequestProxy>& proxy = iter.Data();
    3079             : 
    3080           0 :     if (doc) {
    3081           0 :       doc->StyleImageLoader()->DeregisterCSSImage(this);
    3082             :     }
    3083             : 
    3084           0 :     if (proxy) {
    3085           0 :       proxy->CancelAndForgetObserver(NS_BINDING_ABORTED);
    3086             :     }
    3087             : 
    3088           0 :     iter.Remove();
    3089             :   }
    3090           0 : }
    3091             : 
    3092             : size_t
    3093           0 : css::ComplexColorValue::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
    3094             : {
    3095             :   // Only measure it if it's unshared, to avoid double-counting.
    3096           0 :   size_t n = 0;
    3097           0 :   if (mRefCnt <= 1) {
    3098           0 :     n += aMallocSizeOf(this);
    3099             :   }
    3100           0 :   return n;
    3101             : }
    3102             : 
    3103         141 : nsCSSValueGradientStop::nsCSSValueGradientStop()
    3104             :   : mLocation(eCSSUnit_None),
    3105             :     mColor(eCSSUnit_Null),
    3106         141 :     mIsInterpolationHint(false)
    3107             : {
    3108         141 :   MOZ_COUNT_CTOR(nsCSSValueGradientStop);
    3109         141 : }
    3110             : 
    3111           0 : nsCSSValueGradientStop::nsCSSValueGradientStop(const nsCSSValueGradientStop& aOther)
    3112             :   : mLocation(aOther.mLocation),
    3113             :     mColor(aOther.mColor),
    3114           0 :     mIsInterpolationHint(aOther.mIsInterpolationHint)
    3115             : {
    3116           0 :   MOZ_COUNT_CTOR(nsCSSValueGradientStop);
    3117           0 : }
    3118             : 
    3119          38 : nsCSSValueGradientStop::~nsCSSValueGradientStop()
    3120             : {
    3121          19 :   MOZ_COUNT_DTOR(nsCSSValueGradientStop);
    3122          19 : }
    3123             : 
    3124             : size_t
    3125           6 : nsCSSValueGradientStop::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    3126             : {
    3127           6 :   size_t n = 0;
    3128           6 :   n += mLocation.SizeOfExcludingThis(aMallocSizeOf);
    3129           6 :   n += mColor   .SizeOfExcludingThis(aMallocSizeOf);
    3130           6 :   return n;
    3131             : }
    3132             : 
    3133          51 : nsCSSValueGradient::nsCSSValueGradient(bool aIsRadial,
    3134          51 :                                        bool aIsRepeating)
    3135             :   : mIsRadial(aIsRadial),
    3136             :     mIsRepeating(aIsRepeating),
    3137             :     mIsLegacySyntax(false),
    3138             :     mIsMozLegacySyntax(false),
    3139             :     mIsExplicitSize(false),
    3140             :     mBgPos(eCSSUnit_None),
    3141          51 :     mAngle(eCSSUnit_None)
    3142             : {
    3143          51 :   mRadialValues[0].SetNoneValue();
    3144          51 :   mRadialValues[1].SetNoneValue();
    3145          51 : }
    3146             : 
    3147             : size_t
    3148           2 : nsCSSValueGradient::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    3149             : {
    3150             :   // Only measure it if it's unshared, to avoid double-counting.
    3151           2 :   size_t n = 0;
    3152           2 :   if (mRefCnt <= 1) {
    3153           2 :     n += aMallocSizeOf(this);
    3154           2 :     n += mBgPos.SizeOfExcludingThis(aMallocSizeOf);
    3155           2 :     n += mAngle.SizeOfExcludingThis(aMallocSizeOf);
    3156           2 :     n += mRadialValues[0].SizeOfExcludingThis(aMallocSizeOf);
    3157           2 :     n += mRadialValues[1].SizeOfExcludingThis(aMallocSizeOf);
    3158           2 :     n += mStops.ShallowSizeOfExcludingThis(aMallocSizeOf);
    3159           8 :     for (uint32_t i = 0; i < mStops.Length(); i++) {
    3160           6 :       n += mStops[i].SizeOfExcludingThis(aMallocSizeOf);
    3161             :     }
    3162             :   }
    3163           2 :   return n;
    3164             : }
    3165             : 
    3166             : // --- nsCSSValueTokenStream ------------
    3167             : 
    3168         606 : nsCSSValueTokenStream::nsCSSValueTokenStream()
    3169             :   : mPropertyID(eCSSProperty_UNKNOWN)
    3170             :   , mShorthandPropertyID(eCSSProperty_UNKNOWN)
    3171         606 :   , mLevel(SheetType::Count)
    3172         606 : {}
    3173             : 
    3174           7 : nsCSSValueTokenStream::~nsCSSValueTokenStream()
    3175           7 : {}
    3176             : 
    3177             : size_t
    3178           0 : nsCSSValueTokenStream::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    3179             : {
    3180             :   // Only measure it if it's unshared, to avoid double-counting.
    3181           0 :   size_t n = 0;
    3182           0 :   if (mRefCnt <= 1) {
    3183           0 :     n += aMallocSizeOf(this);
    3184           0 :     n += mTokenStream.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
    3185             :   }
    3186           0 :   return n;
    3187             : }
    3188             : 
    3189             : // --- nsCSSValueFloatColor -------------
    3190             : 
    3191             : bool
    3192           0 : nsCSSValueFloatColor::operator==(nsCSSValueFloatColor& aOther) const
    3193             : {
    3194           0 :   return mComponent1 == aOther.mComponent1 &&
    3195           0 :          mComponent2 == aOther.mComponent2 &&
    3196           0 :          mComponent3 == aOther.mComponent3 &&
    3197           0 :          mAlpha == aOther.mAlpha;
    3198             : }
    3199             : 
    3200             : nscolor
    3201          59 : nsCSSValueFloatColor::GetColorValue(nsCSSUnit aUnit) const
    3202             : {
    3203          59 :   MOZ_ASSERT(nsCSSValue::IsFloatColorUnit(aUnit), "unexpected unit");
    3204             : 
    3205             :   // We should clamp each component value since eCSSUnit_PercentageRGBColor
    3206             :   // and eCSSUnit_PercentageRGBAColor may store values greater than 1.0.
    3207          59 :   if (aUnit == eCSSUnit_PercentageRGBColor ||
    3208             :       aUnit == eCSSUnit_PercentageRGBAColor) {
    3209           0 :     return NS_RGBA(
    3210             :       // We need to clamp before multiplying by 255.0f to avoid overflow.
    3211             :       NSToIntRound(mozilla::clamped(mComponent1, 0.0f, 1.0f) * 255.0f),
    3212             :       NSToIntRound(mozilla::clamped(mComponent2, 0.0f, 1.0f) * 255.0f),
    3213             :       NSToIntRound(mozilla::clamped(mComponent3, 0.0f, 1.0f) * 255.0f),
    3214             :       NSToIntRound(mozilla::clamped(mAlpha, 0.0f, 1.0f) * 255.0f));
    3215             :   }
    3216             : 
    3217             :   // HSL color
    3218          59 :   MOZ_ASSERT(aUnit == eCSSUnit_HSLColor ||
    3219             :              aUnit == eCSSUnit_HSLAColor);
    3220          59 :   nscolor hsl = NS_HSL2RGB(mComponent1, mComponent2, mComponent3);
    3221          59 :   return NS_RGBA(NS_GET_R(hsl),
    3222             :                  NS_GET_G(hsl),
    3223             :                  NS_GET_B(hsl),
    3224             :                  NSToIntRound(mAlpha * 255.0f));
    3225             : }
    3226             : 
    3227             : bool
    3228           0 : nsCSSValueFloatColor::IsNonTransparentColor() const
    3229             : {
    3230           0 :   return mAlpha > 0.0f;
    3231             : }
    3232             : 
    3233             : void
    3234           0 : nsCSSValueFloatColor::AppendToString(nsCSSUnit aUnit, nsAString& aResult) const
    3235             : {
    3236             :   // Similar to the rgb()/rgba() case in nsCSSValue::AppendToString. We omit the
    3237             :   // alpha component if it's equal to 1.0f (full opaque). Also, we try to
    3238             :   // preserve the author-specified function name, unless it's rgba()/hsla() and
    3239             :   // we're omitting the alpha component - then we use rgb()/hsl().
    3240           0 :   MOZ_ASSERT(nsCSSValue::IsFloatColorUnit(aUnit), "unexpected unit");
    3241             : 
    3242           0 :   bool showAlpha = (mAlpha != 1.0f);
    3243           0 :   bool isHSL = (aUnit == eCSSUnit_HSLColor ||
    3244           0 :                 aUnit == eCSSUnit_HSLAColor);
    3245             : 
    3246           0 :   if (isHSL) {
    3247           0 :     aResult.AppendLiteral("hsl");
    3248             :   } else {
    3249           0 :     aResult.AppendLiteral("rgb");
    3250             :   }
    3251           0 :   if (showAlpha && (aUnit == eCSSUnit_HSLAColor || aUnit == eCSSUnit_PercentageRGBAColor)) {
    3252           0 :     aResult.AppendLiteral("a(");
    3253             :   } else {
    3254           0 :     aResult.Append('(');
    3255             :   }
    3256           0 :   if (isHSL) {
    3257           0 :     aResult.AppendFloat(mComponent1 * 360.0f);
    3258           0 :     aResult.AppendLiteral(", ");
    3259             :   } else {
    3260           0 :     aResult.AppendFloat(mComponent1 * 100.0f);
    3261           0 :     aResult.AppendLiteral("%, ");
    3262             :   }
    3263           0 :   aResult.AppendFloat(mComponent2 * 100.0f);
    3264           0 :   aResult.AppendLiteral("%, ");
    3265           0 :   aResult.AppendFloat(mComponent3 * 100.0f);
    3266           0 :   if (showAlpha) {
    3267           0 :     aResult.AppendLiteral("%, ");
    3268           0 :     aResult.AppendFloat(mAlpha);
    3269           0 :     aResult.Append(')');
    3270             :   } else {
    3271           0 :     aResult.AppendLiteral("%)");
    3272             :   }
    3273           0 : }
    3274             : 
    3275             : size_t
    3276           4 : nsCSSValueFloatColor::SizeOfIncludingThis(
    3277             :                                       mozilla::MallocSizeOf aMallocSizeOf) const
    3278             : {
    3279             :   // Only measure it if it's unshared, to avoid double-counting.
    3280           4 :   size_t n = 0;
    3281           4 :   if (mRefCnt <= 1) {
    3282           4 :     n += aMallocSizeOf(this);
    3283             :   }
    3284           4 :   return n;
    3285             : }
    3286             : 
    3287             : // --- nsCSSCornerSizes -----------------
    3288             : 
    3289           0 : nsCSSCornerSizes::nsCSSCornerSizes(void)
    3290             : {
    3291           0 :   MOZ_COUNT_CTOR(nsCSSCornerSizes);
    3292           0 : }
    3293             : 
    3294           0 : nsCSSCornerSizes::nsCSSCornerSizes(const nsCSSCornerSizes& aCopy)
    3295             :   : mTopLeft(aCopy.mTopLeft),
    3296             :     mTopRight(aCopy.mTopRight),
    3297             :     mBottomRight(aCopy.mBottomRight),
    3298           0 :     mBottomLeft(aCopy.mBottomLeft)
    3299             : {
    3300           0 :   MOZ_COUNT_CTOR(nsCSSCornerSizes);
    3301           0 : }
    3302             : 
    3303           0 : nsCSSCornerSizes::~nsCSSCornerSizes()
    3304             : {
    3305           0 :   MOZ_COUNT_DTOR(nsCSSCornerSizes);
    3306           0 : }
    3307             : 
    3308             : void
    3309           0 : nsCSSCornerSizes::Reset()
    3310             : {
    3311           0 :   NS_FOR_CSS_FULL_CORNERS(corner) {
    3312           0 :     this->GetCorner(corner).Reset();
    3313             :   }
    3314           0 : }
    3315             : 
    3316             : static_assert(eCornerTopLeft == 0 && eCornerTopRight == 1 &&
    3317             :               eCornerBottomRight == 2 && eCornerBottomLeft == 3,
    3318             :               "box corner constants not tl/tr/br/bl == 0/1/2/3");
    3319             : 
    3320             : /* static */ const nsCSSCornerSizes::corner_type
    3321             : nsCSSCornerSizes::corners[4] = {
    3322             :   &nsCSSCornerSizes::mTopLeft,
    3323             :   &nsCSSCornerSizes::mTopRight,
    3324             :   &nsCSSCornerSizes::mBottomRight,
    3325             :   &nsCSSCornerSizes::mBottomLeft,
    3326             : };
    3327             : 
    3328             : size_t
    3329           0 : mozilla::css::GridTemplateAreasValue::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
    3330             : {
    3331             :   // Only measure it if it's unshared, to avoid double-counting.
    3332           0 :   size_t n = 0;
    3333           0 :   if (mRefCnt <= 1) {
    3334           0 :     n += aMallocSizeOf(this);
    3335           0 :     n += mNamedAreas.ShallowSizeOfExcludingThis(aMallocSizeOf);
    3336           0 :     n += mTemplates.ShallowSizeOfExcludingThis(aMallocSizeOf);
    3337             :   }
    3338           0 :   return n;
    3339             : }

Generated by: LCOV version 1.13