Bug 1452987: Simplify ImageValue. r?heycam draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 10 Apr 2018 16:54:57 +0200
changeset 779761 47a74ce18a7207c3b73fae1a4e593f4352dbf116
parent 779760 9df7b71c9686d2d8f1a3f51bdacd3ad79c2ed2ea
child 779955 cee73b6cc2557ca9c4f673adcb9c2d4975ebfce8
push id105862
push userbmo:emilio@crisal.io
push dateTue, 10 Apr 2018 14:58:37 +0000
reviewersheycam
bugs1452987
milestone61.0a1
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
servo/components/style/gecko/url.rs
--- 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");
--- a/servo/components/style/gecko/url.rs
+++ b/servo/components/style/gecko/url.rs
@@ -50,25 +50,20 @@ impl CssUrl {
     /// URLs in gecko, so we just return false here.
     /// use its |resolved| status.
     pub fn is_invalid(&self) -> bool {
         false
     }
 
     /// Convert from URLValueData to SpecifiedUrl.
     unsafe fn from_url_value_data(url: &URLValueData) -> Result<Self, ()> {
+        let arc_type =
+            &url.mString as *const _ as *const RawOffsetArc<String>;
         Ok(CssUrl {
-            serialization: if url.mUsingRustString {
-                let arc_type = url.mStrings.mRustString.as_ref()
-                    as *const _ as
-                    *const RawOffsetArc<String>;
-                Arc::from_raw_offset((*arc_type).clone())
-            } else {
-                Arc::new(url.mStrings.mString.as_ref().to_string())
-            },
+            serialization: Arc::from_raw_offset((*arc_type).clone()),
             extra_data: url.mExtraData.to_safe(),
         })
     }
 
     /// Returns true if this URL looks like a fragment.
     /// See https://drafts.csswg.org/css-values/#local-urls
     pub fn is_fragment(&self) -> bool {
         self.as_str().chars().next().map_or(false, |c| c == '#')