Bug 1452987: Simplify ImageValue. r=heycam
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 10 Apr 2018 16:54:57 +0200
changeset 466261 238555703674d85aa681ff5dd5462fb1db85a3ac
parent 466260 95d2a906ee827a1fa5186ad22c1a08c6c81545f0
child 466262 2961729885f5063e8e4b224993ab3980025e2469
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1452987
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1452987: Simplify ImageValue. r=heycam MozReview-Commit-ID: 5LRaaEPSSdY
dom/base/Element.h
dom/base/nsAttrValue.cpp
dom/base/nsAttrValue.h
dom/base/nsAttrValueInlines.h
dom/html/nsGenericHTMLElement.cpp
layout/style/ServoSpecifiedValues.cpp
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
layout/style/nsStyleUtil.cpp
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -60,16 +60,19 @@ class nsGlobalWindowOuter;
 class nsDOMCSSAttributeDeclaration;
 class nsISMILAttr;
 class nsDocument;
 class nsDOMStringMap;
 
 namespace mozilla {
 class DeclarationBlock;
 class TextEditor;
+namespace css {
+  struct URLValue;
+} // namespace css
 namespace dom {
   struct AnimationFilter;
   struct ScrollIntoViewOptions;
   struct ScrollToOptions;
   class DOMIntersectionObserver;
   class DOMMatrixReadOnly;
   class ElementOrCSSPseudoElement;
   class UnrestrictedDoubleOrKeyframeAnimationOptions;
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -25,21 +25,16 @@
 #include "nsReadableUtils.h"
 #include "nsHTMLCSSStyleSheet.h"
 #include "nsCSSParser.h"
 #include "nsStyledElement.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #include <algorithm>
 
-#ifdef LoadImage
-// Undefine LoadImage to prevent naming conflict with Windows.
-#undef LoadImage
-#endif
-
 using namespace mozilla;
 
 #define MISC_STR_PTR(_cont) \
   reinterpret_cast<void*>((_cont)->mStringBits & NS_ATTRVALUE_POINTERVALUE_MASK)
 
 bool
 MiscContainer::GetString(nsAString& aString) const
 {
@@ -300,21 +295,16 @@ nsAttrValue::SetTo(const nsAttrValue& aO
     {
       MOZ_CRASH("These should be refcounted!");
     }
     case eURL:
     {
       NS_ADDREF(cont->mValue.mURL = otherCont->mValue.mURL);
       break;
     }
-    case eImage:
-    {
-      NS_ADDREF(cont->mValue.mImage = otherCont->mValue.mImage);
-      break;
-    }
     case eAtomArray:
     {
       if (!EnsureEmptyAtomArray() ||
           !GetAtomArrayValue()->AppendElements(*otherCont->mValue.mAtomArray)) {
         Reset();
         return;
       }
       break;
@@ -411,17 +401,17 @@ nsAttrValue::SetTo(already_AddRefed<Decl
   cont->mValue.mCSSDeclaration = aValue.take();
   cont->mType = eCSSDeclaration;
   NS_ADDREF(cont);
   SetMiscAtomOrString(aSerialized);
   MOZ_ASSERT(cont->mValue.mRefCount == 1);
 }
 
 void
-nsAttrValue::SetTo(css::URLValue* aValue, const nsAString* aSerialized)
+nsAttrValue::SetTo(nsIURI* aValue, const nsAString* aSerialized)
 {
   MiscContainer* cont = EnsureEmptyMiscContainer();
   NS_ADDREF(cont->mValue.mURL = aValue);
   cont->mType = eURL;
   SetMiscAtomOrString(aSerialized);
 }
 
 void
@@ -873,20 +863,17 @@ nsAttrValue::HashValue() const
     case eColor:
     {
       return cont->mValue.mColor;
     }
     case eCSSDeclaration:
     {
       return NS_PTR_TO_INT32(cont->mValue.mCSSDeclaration);
     }
-    // Intentionally identical, so that loading the image does not change the
-    // hash code.
     case eURL:
-    case eImage:
     {
       nsString str;
       ToString(str);
       return HashString(str);
     }
     case eAtomArray:
     {
       uint32_t hash = 0;
@@ -987,20 +974,16 @@ nsAttrValue::Equals(const nsAttrValue& a
     {
       return thisCont->mValue.mCSSDeclaration ==
                otherCont->mValue.mCSSDeclaration;
     }
     case eURL:
     {
       return thisCont->mValue.mURL == otherCont->mValue.mURL;
     }
-    case eImage:
-    {
-      return thisCont->mValue.mImage == otherCont->mValue.mImage;
-    }
     case eAtomArray:
     {
       // For classlists we could be insensitive to order, however
       // classlists are never mapped attributes so they are never compared.
 
       if (!(*thisCont->mValue.mAtomArray == *otherCont->mValue.mAtomArray)) {
         return false;
       }
@@ -1676,38 +1659,16 @@ nsAttrValue::ParseIntMarginValue(const n
 
   MiscContainer* cont = EnsureEmptyMiscContainer();
   cont->mValue.mIntMargin = new nsIntMargin(margins);
   cont->mType = eIntMarginValue;
   SetMiscAtomOrString(&aString);
   return true;
 }
 
-void
-nsAttrValue::LoadImage(nsIDocument* aDocument)
-{
-  NS_ASSERTION(Type() == eURL, "wrong type");
-
-  MiscContainer* cont = GetMiscContainer();
-  mozilla::css::URLValue* url = cont->mValue.mURL;
-
-  NS_ASSERTION(!url->IsStringEmpty(),
-               "How did we end up with an empty string for eURL");
-
-  mozilla::css::ImageValue* image =
-      mozilla::css::ImageValue::CreateFromURLValue(url,
-                                                   aDocument,
-                                                   mozilla::CORSMode::CORS_NONE);
-
-  NS_ADDREF(image);
-  cont->mValue.mImage = image;
-  NS_RELEASE(url);
-  cont->mType = eImage;
-}
-
 bool
 nsAttrValue::ParseStyleAttribute(const nsAString& aString,
                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsStyledElement* aElement)
 {
   nsIDocument* ownerDoc = aElement->OwnerDoc();
   nsHTMLCSSStyleSheet* sheet = ownerDoc->GetInlineStyleSheet();
   nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURIForStyleAttr();
@@ -1864,21 +1825,16 @@ nsAttrValue::ClearMiscContainer()
           NS_RELEASE(cont->mValue.mCSSDeclaration);
           break;
         }
         case eURL:
         {
           NS_RELEASE(cont->mValue.mURL);
           break;
         }
-        case eImage:
-        {
-          NS_RELEASE(cont->mValue.mImage);
-          break;
-        }
         case eAtomArray:
         {
           delete cont->mValue.mAtomArray;
           break;
         }
         case eIntMarginValue:
         {
           delete cont->mValue.mIntMargin;
--- a/dom/base/nsAttrValue.h
+++ b/dom/base/nsAttrValue.h
@@ -25,29 +25,23 @@
 #include "SVGAttrValueWrapper.h"
 #include "nsTArrayForwardDeclare.h"
 #include "nsAtom.h"
 #include "mozilla/AtomArray.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/EnumTypeTraits.h"
 
-// Undefine LoadImage to prevent naming conflict with Windows.
-#undef LoadImage
-
 class nsIDocument;
+class nsIURI;
 class nsStyledElement;
 struct MiscContainer;
 
 namespace mozilla {
 class DeclarationBlock;
-namespace css {
-struct URLValue;
-struct ImageValue;
-} // namespace css
 } // namespace mozilla
 
 #define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
 
 #define NS_ATTRVALUE_BASETYPE_MASK (uintptr_t(3))
 #define NS_ATTRVALUE_POINTERVALUE_MASK (~NS_ATTRVALUE_BASETYPE_MASK)
 
 #define NS_ATTRVALUE_INTEGERTYPE_BITS 4
@@ -145,17 +139,17 @@ public:
   void SetTo(const nsAttrValue& aOther);
   void SetTo(const nsAString& aValue);
   void SetTo(nsAtom* aValue);
   void SetTo(int16_t aInt);
   void SetTo(int32_t aInt, const nsAString* aSerialized);
   void SetTo(double aValue, const nsAString* aSerialized);
   void SetTo(already_AddRefed<mozilla::DeclarationBlock> aValue,
              const nsAString* aSerialized);
-  void SetTo(mozilla::css::URLValue* aValue, const nsAString* aSerialized);
+  void SetTo(nsIURI* aValue, const nsAString* aSerialized);
   void SetTo(const nsIntMargin& aValue);
   void SetTo(const nsSVGAngle& aValue, const nsAString* aSerialized);
   void SetTo(const nsSVGIntegerPair& aValue, const nsAString* aSerialized);
   void SetTo(const nsSVGLength2& aValue, const nsAString* aSerialized);
   void SetTo(const mozilla::SVGLengthList& aValue,
              const nsAString* aSerialized);
   void SetTo(const mozilla::SVGNumberList& aValue,
              const nsAString* aSerialized);
@@ -196,18 +190,17 @@ public:
   const nsCheapString GetStringValue() const;
   inline nsAtom* GetAtomValue() const;
   inline int32_t GetIntegerValue() const;
   bool GetColorValue(nscolor& aColor) const;
   inline int16_t GetEnumValue() const;
   inline float GetPercentValue() const;
   inline mozilla::AtomArray* GetAtomArrayValue() const;
   inline mozilla::DeclarationBlock* GetCSSDeclarationValue() const;
-  inline mozilla::css::URLValue* GetURLValue() const;
-  inline mozilla::css::ImageValue* GetImageValue() const;
+  inline nsIURI* GetURLValue() const;
   inline double GetDoubleValue() const;
   bool GetIntMarginValue(nsIntMargin& aMargin) const;
 
   /**
    * Returns the string corresponding to the stored enum value.
    *
    * @param aResult   the string representing the enum tag
    * @param aRealTag  wheter we want to have the real tag or the saved one
@@ -417,23 +410,16 @@ public:
    * an nsIntMargin.
    *
    * @param aString the string to parse
    * @return whether the value could be parsed
    */
   bool ParseIntMarginValue(const nsAString& aString);
 
   /**
-   * Convert a URL nsAttrValue to an Image nsAttrValue.
-   *
-   * @param aDocument the document this nsAttrValue belongs to.
-   */
-  void LoadImage(nsIDocument* aDocument);
-
-  /**
    * Parse a string into a CSS style rule.
    *
    * @param aString the style attribute value to be parsed.
    * @param aElement the element the attribute is set on.
    * @param aMaybeScriptedPrincipal if available, the scripted principal
    *        responsible for this attribute value, as passed to
    *        Element::ParseAttribute.
    */
--- a/dom/base/nsAttrValueInlines.h
+++ b/dom/base/nsAttrValueInlines.h
@@ -37,18 +37,17 @@ struct MiscContainer final
   union {
     struct {
       union {
         int32_t mInteger;
         nscolor mColor;
         uint32_t mEnumValue;
         int32_t mPercent;
         mozilla::DeclarationBlock* mCSSDeclaration;
-        mozilla::css::URLValue* mURL;
-        mozilla::css::ImageValue* mImage;
+        nsIURI* mURL;
         mozilla::AtomArray* mAtomArray;
         nsIntMargin* mIntMargin;
         const nsSVGAngle* mSVGAngle;
         const nsSVGIntegerPair* mSVGIntegerPair;
         const nsSVGLength2* mSVGLength;
         const mozilla::SVGLengthList* mSVGLengthList;
         const mozilla::SVGNumberList* mSVGNumberList;
         const nsSVGNumberPair* mSVGNumberPair;
@@ -167,30 +166,23 @@ nsAttrValue::GetAtomArrayValue() const
 
 inline mozilla::DeclarationBlock*
 nsAttrValue::GetCSSDeclarationValue() const
 {
   NS_PRECONDITION(Type() == eCSSDeclaration, "wrong type");
   return GetMiscContainer()->mValue.mCSSDeclaration;
 }
 
-inline mozilla::css::URLValue*
+inline nsIURI*
 nsAttrValue::GetURLValue() const
 {
   NS_PRECONDITION(Type() == eURL, "wrong type");
   return GetMiscContainer()->mValue.mURL;
 }
 
-inline mozilla::css::ImageValue*
-nsAttrValue::GetImageValue() const
-{
-  NS_PRECONDITION(Type() == eImage, "wrong type");
-  return GetMiscContainer()->mValue.mImage;
-}
-
 inline double
 nsAttrValue::GetDoubleValue() const
 {
   NS_PRECONDITION(Type() == eDoubleValue, "wrong type");
   return GetMiscContainer()->mDoubleValue;
 }
 
 inline bool
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -916,21 +916,17 @@ nsGenericHTMLElement::ParseBackgroundAtt
     nsIDocument* doc = OwnerDoc();
     nsCOMPtr<nsIURI> baseURI = GetBaseURI();
     nsCOMPtr<nsIURI> uri;
     nsresult rv = nsContentUtils::NewURIWithDocumentCharset(
         getter_AddRefs(uri), aValue, doc, baseURI);
     if (NS_FAILED(rv)) {
       return false;
     }
-
-    mozilla::css::URLValue *url =
-      new mozilla::css::URLValue(uri, aValue, baseURI, doc->GetDocumentURI(),
-                                 NodePrincipal());
-    aResult.SetTo(url, &aValue);
+    aResult.SetTo(uri, &aValue);
     return true;
   }
 
   return false;
 }
 
 bool
 nsGenericHTMLElement::IsAttributeMapped(const nsAtom* aAttribute) const
--- a/layout/style/ServoSpecifiedValues.cpp
+++ b/layout/style/ServoSpecifiedValues.cpp
@@ -106,17 +106,16 @@ void
 ServoSpecifiedValues::SetTextDecorationColorOverride()
 {
   Servo_DeclarationBlock_SetTextDecorationColorOverride(mDecl);
 }
 
 void
 ServoSpecifiedValues::SetBackgroundImage(nsAttrValue& aValue)
 {
-  if (aValue.Type() != nsAttrValue::eURL &&
-      aValue.Type() != nsAttrValue::eImage) {
+  if (aValue.Type() != nsAttrValue::eURL) {
     return;
   }
   nsAutoString str;
   aValue.ToString(str);
   Servo_DeclarationBlock_SetBackgroundImage(
     mDecl, str, mDocument->DefaultStyleAttrURLData());
 }
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -693,29 +693,16 @@ nsCSSValue::GetCalcValue() const
     result.mLength = length.GetPixelLength();
     result.mPercent = percent.GetPercentValue();
     result.mHasPercent = true;
   }
 
   return result;
 }
 
-void nsCSSValue::StartImageLoad(nsIDocument* aDocument,
-                                mozilla::CORSMode aCORSMode) const
-{
-  MOZ_ASSERT(eCSSUnit_URL == mUnit, "Not a URL value!");
-  mozilla::css::ImageValue* image =
-      mozilla::css::ImageValue::CreateFromURLValue(mValue.mURL,
-                                                   aDocument,
-                                                   aCORSMode);
-
-  nsCSSValue* writable = const_cast<nsCSSValue*>(this);
-  writable->SetImageValue(image);
-}
-
 nsCSSValue::Array*
 nsCSSValue::InitFunction(nsCSSKeyword aFunctionId, uint32_t aNumArgs)
 {
   RefPtr<nsCSSValue::Array> func = Array::Create(aNumArgs + 1);
   func->Item(0).SetIntValue(aFunctionId, eCSSUnit_Enumerated);
   SetArrayValue(func, eCSSUnit_Function);
   return func;
 }
@@ -1148,87 +1135,51 @@ nsCSSValue::Array::SizeOfIncludingThis(m
   size_t n = aMallocSizeOf(this);
   for (size_t i = 0; i < mCount; i++) {
     n += mArray[i].SizeOfExcludingThis(aMallocSizeOf);
   }
   return n;
 }
 
 css::URLValueData::URLValueData(already_AddRefed<nsIURI> aURI,
-                                const nsAString& aString,
-                                already_AddRefed<URLExtraData> aExtraData)
-  : mURI(Move(aURI))
-  , mExtraData(Move(aExtraData))
-  , mURIResolved(true)
-  , mStrings(aString)
-  , mUsingRustString(false)
-{
-  MOZ_ASSERT(mExtraData);
-  MOZ_ASSERT(mExtraData->GetPrincipal());
-}
-
-css::URLValueData::URLValueData(already_AddRefed<nsIURI> aURI,
                                 ServoRawOffsetArc<RustString> aString,
                                 already_AddRefed<URLExtraData> aExtraData)
   : mURI(Move(aURI))
   , mExtraData(Move(aExtraData))
   , mURIResolved(true)
-  , mStrings(aString)
-  , mUsingRustString(true)
-{
-  MOZ_ASSERT(mExtraData);
-  MOZ_ASSERT(mExtraData->GetPrincipal());
-}
-
-css::URLValueData::URLValueData(const nsAString& aString,
-                                already_AddRefed<URLExtraData> aExtraData)
-  : mExtraData(Move(aExtraData))
-  , mURIResolved(false)
-  , mStrings(aString)
-  , mUsingRustString(false)
+  , mString(aString)
 {
   MOZ_ASSERT(mExtraData);
   MOZ_ASSERT(mExtraData->GetPrincipal());
 }
 
 css::URLValueData::URLValueData(ServoRawOffsetArc<RustString> aString,
                                 already_AddRefed<URLExtraData> aExtraData)
   : mExtraData(Move(aExtraData))
   , mURIResolved(false)
-  , mStrings(aString)
-  , mUsingRustString(true)
+  , mString(aString)
 {
   MOZ_ASSERT(mExtraData);
   MOZ_ASSERT(mExtraData->GetPrincipal());
 }
 
 css::URLValueData::~URLValueData()
 {
-  if (mUsingRustString) {
-    Servo_ReleaseArcStringData(&mStrings.mRustString);
-  } else {
-    mStrings.mString.~nsString();
-  }
+  Servo_ReleaseArcStringData(&mString);
 }
 
 bool
 css::URLValueData::Equals(const URLValueData& aOther) const
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   bool eq;
   const URLExtraData* self = mExtraData;
   const URLExtraData* other = aOther.mExtraData;
-  bool stringsEqual;
-  if (mUsingRustString && aOther.mUsingRustString) {
-    stringsEqual = GetRustString() == aOther.GetRustString();
-  } else {
-    stringsEqual = GetUTF16String() == aOther.GetUTF16String();
-  }
-  return stringsEqual &&
+  return GetString() == aOther.GetString() &&
           (GetURI() == aOther.GetURI() || // handles null == null
            (mURI && aOther.mURI &&
             NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
             eq)) &&
           (self->BaseURI() == other->BaseURI() ||
            (NS_SUCCEEDED(self->BaseURI()->Equals(other->BaseURI(), &eq)) &&
             eq)) &&
           (self->GetPrincipal() == other->GetPrincipal() ||
@@ -1237,109 +1188,61 @@ css::URLValueData::Equals(const URLValue
 }
 
 bool
 css::URLValueData::DefinitelyEqualURIs(const URLValueData& aOther) const
 {
   if (mExtraData->BaseURI() != aOther.mExtraData->BaseURI()) {
     return false;
   }
-  if (mUsingRustString && aOther.mUsingRustString) {
-    return GetRustString() == aOther.GetRustString();
-  }
-  return GetUTF16StringForAnyThread() == aOther.GetUTF16StringForAnyThread();
+  return GetString() == aOther.GetString();
 }
 
 bool
 css::URLValueData::DefinitelyEqualURIsAndPrincipal(
     const URLValueData& aOther) const
 {
   return mExtraData->GetPrincipal() == aOther.mExtraData->GetPrincipal() &&
          DefinitelyEqualURIs(aOther);
 }
 
 nsDependentCSubstring
-css::URLValueData::GetRustString() const
+css::URLValueData::GetString() const
 {
   const uint8_t* chars;
   uint32_t len;
-  Servo_GetArcStringData(mStrings.mRustString.mPtr, &chars, &len);
+  Servo_GetArcStringData(mString.mPtr, &chars, &len);
   return nsDependentCSubstring(reinterpret_cast<const char*>(chars), len);
 }
 
-bool
-css::URLValueData::IsStringEmpty() const
-{
-  if (mUsingRustString) {
-    return GetRustString().IsEmpty();
-  }
-  return mStrings.mString.IsEmpty();
-}
-
-const nsString&
-css::URLValueData::GetUTF16String() const
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (mUsingRustString) {
-    nsDependentCSubstring rust = GetRustString();
-    nsString converted = NS_ConvertUTF8toUTF16(rust);
-    Servo_ReleaseArcStringData(&mStrings.mRustString);
-    new (&mStrings) RustOrGeckoString(converted);
-    mUsingRustString = false;
-  }
-  return mStrings.mString;
-}
-
-nsString
-css::URLValueData::GetUTF16StringForAnyThread() const
-{
-  if (!mUsingRustString) {
-    return mStrings.mString;
-  }
-  nsDependentCSubstring rust = GetRustString();
-  return NS_ConvertUTF8toUTF16(rust);
-}
-
 nsIURI*
 css::URLValueData::GetURI() const
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (!mURIResolved) {
     MOZ_ASSERT(!mURI);
     nsCOMPtr<nsIURI> newURI;
-    if (!mUsingRustString) {
-      NS_NewURI(getter_AddRefs(newURI),
-                NS_ConvertUTF16toUTF8(mStrings.mString),
-                nullptr, mExtraData->BaseURI());
-    } else {
-      NS_NewURI(getter_AddRefs(newURI),
-                GetRustString(),
-                nullptr, mExtraData->BaseURI());
-    }
+    NS_NewURI(getter_AddRefs(newURI),
+              GetString(),
+              nullptr, mExtraData->BaseURI());
     mURI = newURI.forget();
     mURIResolved = true;
   }
 
   return mURI;
 }
 
 bool
 css::URLValueData::IsLocalRef() const
 {
   if (mIsLocalRef.isNothing()) {
     // IsLocalRefURL is O(N), use it only when IsLocalRef is called.
-    if (mUsingRustString) {
-      mIsLocalRef.emplace(nsContentUtils::IsLocalRefURL(GetRustString()));
-    } else {
-      mIsLocalRef.emplace(nsContentUtils::IsLocalRefURL(mStrings.mString));
-    }
+    mIsLocalRef.emplace(nsContentUtils::IsLocalRefURL(GetString()));
   }
-
   return mIsLocalRef.value();
 }
 
 bool
 css::URLValueData::HasRef() const
 {
   bool result = false;
 
@@ -1359,19 +1262,17 @@ css::URLValueData::HasRef() const
 
   return result;
 }
 
 bool
 css::URLValueData::MightHaveRef() const
 {
   if (mMightHaveRef.isNothing()) {
-    bool result = mUsingRustString ?
-        ::MightHaveRef(GetRustString()) :
-        ::MightHaveRef(mStrings.mString);
+    bool result = ::MightHaveRef(GetString());
     if (!ServoStyleSet::IsInServoTraversal()) {
       // Can only cache the result if we're not on a style worker thread.
       mMightHaveRef.emplace(result);
     }
     return result;
   }
 
   return mMightHaveRef.value();
@@ -1443,111 +1344,66 @@ css::URLValueData::EqualsExceptRef(nsIUR
   bool ret = false;
   uri->EqualsExceptRef(aURI, &ret);
   return ret;
 }
 
 size_t
 css::URLValueData::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
-  size_t n = 0;
-  if (!mUsingRustString) {
-    n += mStrings.mString.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
-  }
-
   // Measurement of the following members may be added later if DMD finds it
   // is worthwhile:
   // - mURI
+  // - mString
   // - mExtraData
-  return n;
-}
-
-URLValue::URLValue(const nsAString& aString, nsIURI* aBaseURI, nsIURI* aReferrer,
-                   nsIPrincipal* aOriginPrincipal)
-  : URLValueData(aString, do_AddRef(new URLExtraData(aBaseURI, aReferrer,
-                                                     aOriginPrincipal)))
-{
-  MOZ_ASSERT(NS_IsMainThread());
-}
-
-URLValue::URLValue(nsIURI* aURI, const nsAString& aString, nsIURI* aBaseURI,
-                   nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
-  : URLValueData(do_AddRef(aURI),
-                 aString,
-                 do_AddRef(new URLExtraData(aBaseURI, aReferrer,
-                                            aOriginPrincipal)))
-{
-  MOZ_ASSERT(NS_IsMainThread());
+  return 0;
 }
 
 size_t
 css::URLValue::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   // Only measure it if it's unshared, to avoid double-counting.
   size_t n = 0;
   if (mRefCnt <= 1) {
     n += aMallocSizeOf(this);
     n += URLValueData::SizeOfExcludingThis(aMallocSizeOf);
   }
   return n;
 }
 
-css::ImageValue::ImageValue(nsIURI* aURI, const nsAString& aString,
+css::ImageValue::ImageValue(nsIURI* aURI,
+                            ServoRawOffsetArc<RustString> aString,
                             already_AddRefed<URLExtraData> aExtraData,
                             nsIDocument* aDocument,
                             CORSMode aCORSMode)
   : URLValueData(do_AddRef(aURI), aString, Move(aExtraData))
 {
   mCORSMode = aCORSMode;
   Initialize(aDocument);
 }
 
-css::ImageValue::ImageValue(nsIURI* aURI, ServoRawOffsetArc<RustString> aString,
-                            already_AddRefed<URLExtraData> aExtraData,
-                            nsIDocument* aDocument,
-                            CORSMode aCORSMode)
-  : URLValueData(do_AddRef(aURI), aString, Move(aExtraData))
-{
-  mCORSMode = aCORSMode;
-  Initialize(aDocument);
-}
-
-css::ImageValue::ImageValue(const nsAString& aString,
-                            already_AddRefed<URLExtraData> aExtraData,
-                            CORSMode aCORSMode)
-  : URLValueData(aString, Move(aExtraData))
-{
-  mCORSMode = aCORSMode;
-}
-
 css::ImageValue::ImageValue(ServoRawOffsetArc<RustString> aString,
                             already_AddRefed<URLExtraData> aExtraData,
                             CORSMode aCORSMode)
   : URLValueData(aString, Move(aExtraData))
 {
   mCORSMode = aCORSMode;
 }
 
-/*static*/ css::ImageValue*
+/*static*/ already_AddRefed<css::ImageValue>
 css::ImageValue::CreateFromURLValue(URLValue* aUrl,
                                     nsIDocument* aDocument,
                                     CORSMode aCORSMode)
 {
-  if (aUrl->mUsingRustString) {
-    return new css::ImageValue(aUrl->GetURI(),
-                               Servo_CloneArcStringData(&aUrl->mStrings.mRustString),
-                               do_AddRef(aUrl->mExtraData),
-                               aDocument,
-                               aCORSMode);
-  }
-  return new css::ImageValue(aUrl->GetURI(),
-                             aUrl->mStrings.mString,
-                             do_AddRef(aUrl->mExtraData),
-                             aDocument,
-                             aCORSMode);
+  return do_AddRef(
+    new css::ImageValue(aUrl->GetURI(),
+                        Servo_CloneArcStringData(&aUrl->mString),
+                        do_AddRef(aUrl->mExtraData),
+                        aDocument,
+                        aCORSMode));
 }
 
 void
 css::ImageValue::Initialize(nsIDocument* aDocument)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // NB: If aDocument is not the original document, we may not be able to load
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -95,29 +95,24 @@ namespace css {
 
 struct URLValueData
 {
 protected:
   // Methods are not inline because using an nsIPrincipal means requiring
   // caps, which leads to REQUIRES hell, since this header is included all
   // over.
 
-  // For both constructors aString must not be null.
-  // For both constructors principal of aExtraData must not be null.
+  // aString must not be null.
+  // principal of aExtraData must not be null.
   // Construct with a base URI; this will create the actual URI lazily from
   // aString and aExtraData.
-  URLValueData(const nsAString& aString,
-               already_AddRefed<URLExtraData> aExtraData);
   URLValueData(ServoRawOffsetArc<RustString> aString,
                already_AddRefed<URLExtraData> aExtraData);
   // Construct with the actual URI.
   URLValueData(already_AddRefed<nsIURI> aURI,
-               const nsAString& aString,
-               already_AddRefed<URLExtraData> aExtraData);
-  URLValueData(already_AddRefed<nsIURI> aURI,
                ServoRawOffsetArc<RustString> aString,
                already_AddRefed<URLExtraData> aExtraData);
 
 public:
   // Returns true iff all fields of the two URLValueData objects are equal.
   //
   // Only safe to call on the main thread, since this will call Equals on the
   // nsIURI and nsIPrincipal objects stored on the URLValueData objects.
@@ -158,50 +153,39 @@ public:
   already_AddRefed<nsIURI> ResolveLocalRef(nsIContent* aContent) const;
 
   // Serializes mURI as a computed URI value, taking into account mIsLocalRef
   // and serializing just the fragment if true.
   void GetSourceString(nsString& aRef) const;
 
   bool EqualsExceptRef(nsIURI* aURI) const;
 
-  // Can only be called from the main thread. Returns this URL's UTF-16 representation,
-  // converting and caching its value if necessary.
-  const nsString& GetUTF16String() const;
-  // Returns this URL's UTF-16 representation, converting if necessary.
-  nsString GetUTF16StringForAnyThread() const;
+  bool IsStringEmpty() const
+  {
+    return GetString().IsEmpty();
+  }
 
-  bool IsStringEmpty() const;
+  nsDependentCSubstring GetString() const;
 
 private:
   // mURI stores the lazily resolved URI.  This may be null if the URI is
   // invalid, even once resolved.
   mutable nsCOMPtr<nsIURI> mURI;
+
 public:
   RefPtr<URLExtraData> mExtraData;
+
 private:
-  // Returns a substring based on mStrings.mRustString which should not be exposed
-  // to external consumers.
-  nsDependentCSubstring GetRustString() const;
+  mutable bool mURIResolved;
 
-  mutable bool mURIResolved;
   // mIsLocalRef is set when url starts with a U+0023 number sign(#) character.
   mutable Maybe<bool> mIsLocalRef;
   mutable Maybe<bool> mMightHaveRef;
 
-  mutable union RustOrGeckoString {
-    explicit RustOrGeckoString(const nsAString& aString)
-    : mString(aString) {}
-    explicit RustOrGeckoString(ServoRawOffsetArc<RustString> aString)
-    : mRustString(aString) {}
-    ~RustOrGeckoString() {}
-    nsString mString;
-    mozilla::ServoRawOffsetArc<RustString> mRustString;
-  } mStrings;
-  mutable bool mUsingRustString;
+  mozilla::ServoRawOffsetArc<RustString> mString;
 
 protected:
   // Only used by ImageValue.  Declared up here because otherwise bindgen gets
   // confused by the non-standard-layout packing of the variable up into
   // URLValueData.
   bool mLoadedImage = false;
   CORSMode mCORSMode = CORSMode::CORS_NONE;
 
@@ -218,38 +202,31 @@ private:
   URLValueData(const URLValueData& aOther) = delete;
   URLValueData& operator=(const URLValueData& aOther) = delete;
 
   friend struct ImageValue;
 };
 
 struct URLValue final : public URLValueData
 {
-  // These two constructors are safe to call only on the main thread.
-  URLValue(const nsAString& aString, nsIURI* aBaseURI, nsIURI* aReferrer,
-           nsIPrincipal* aOriginPrincipal);
-  URLValue(nsIURI* aURI, const nsAString& aString, nsIURI* aBaseURI,
-           nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal);
-
-  // This constructor is safe to call from any thread.
   URLValue(ServoRawOffsetArc<RustString> aString,
            already_AddRefed<URLExtraData> aExtraData)
-    : URLValueData(aString, Move(aExtraData)) {}
+    : URLValueData(aString, Move(aExtraData))
+  { }
 
   URLValue(const URLValue&) = delete;
   URLValue& operator=(const URLValue&) = delete;
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 };
 
 struct ImageValue final : public URLValueData
 {
-  static ImageValue* CreateFromURLValue(URLValue* url,
-                                        nsIDocument* aDocument,
-                                        CORSMode aCORSMode);
+  static already_AddRefed<ImageValue>
+    CreateFromURLValue(URLValue*, nsIDocument*, CORSMode);
 
   // Not making the constructor and destructor inline because that would
   // force us to include imgIRequest.h, which leads to REQUIRES hell, since
   // this header is included all over.
   //
   // This constructor is only safe to call from the main thread.
   ImageValue(nsIURI* aURI, const nsAString& aString,
              already_AddRefed<URLExtraData> aExtraData,
@@ -680,25 +657,16 @@ public:
 
   mozilla::css::GridTemplateAreasValue* GetGridTemplateAreas() const
   {
     MOZ_ASSERT(mUnit == eCSSUnit_GridTemplateAreas,
                "not a grid-template-areas value");
     return mValue.mGridTemplateAreas;
   }
 
-  const char16_t* GetOriginalURLValue() const
-  {
-    MOZ_ASSERT(mUnit == eCSSUnit_URL || mUnit == eCSSUnit_Image,
-               "not a URL value");
-    return mUnit == eCSSUnit_URL ?
-             mValue.mURL->GetUTF16String().get() :
-             mValue.mImage->GetUTF16String().get();
-  }
-
   // Not making this inline because that would force us to include
   // imgIRequest.h, which leads to REQUIRES hell, since this header is included
   // all over.
   imgRequestProxy* GetImageValue(nsIDocument* aDocument) const;
 
   // Like GetImageValue, but additionally will pass the imgRequestProxy
   // through nsContentUtils::GetStaticRequest if aPresContent is static.
   already_AddRefed<imgRequestProxy> GetPossiblyStaticImageValue(
--- a/layout/style/nsStyleUtil.cpp
+++ b/layout/style/nsStyleUtil.cpp
@@ -618,18 +618,18 @@ nsStyleUtil::AppendSerializedFontSrc(con
   const nsCSSValue::Array& sources = *aValue.GetArrayValue();
   size_t i = 0;
 
   while (i < sources.Count()) {
     nsAutoString formats;
 
     if (sources[i].GetUnit() == eCSSUnit_URL) {
       aResult.AppendLiteral("url(");
-      nsDependentString url(sources[i].GetOriginalURLValue());
-      nsStyleUtil::AppendEscapedCSSString(url, aResult);
+      nsDependentCSubstring url(sources[i].GetURLStructValue()->GetString());
+      nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(url), aResult);
       aResult.Append(')');
     } else if (sources[i].GetUnit() == eCSSUnit_Local_Font) {
       aResult.AppendLiteral("local(");
       nsDependentString local(sources[i].GetStringBufferValue());
       nsStyleUtil::AppendEscapedCSSString(local, aResult);
       aResult.Append(')');
     } else {
       NS_NOTREACHED("entry in src: descriptor with improper unit");