From e3d24b013a2705ae7f55d17b5c9f25c1effd997c Mon Sep 17 00:00:00 2001
From: Alexandru Michis <malexandru@mozilla.com>
Date: Wed, 23 Jun 2021 01:58:49 +0300
Subject: [PATCH] Backed out changeset 3beb01f5d643 (bug 1717526) for causing
 gtest failures in SpanTest.from_xpcom_collections

CLOSED TREE
---
 dom/bindings/FakeString.h                     |  4 +++
 dom/encoding/TextDecoder.cpp                  |  9 +++---
 intl/uconv/nsScriptableUConv.cpp              | 15 ++++-----
 mfbt/tests/gtest/TestSpan.cpp                 |  7 ++++-
 .../osfile/NativeOSFileInternals.cpp          |  8 ++---
 xpcom/string/nsTSubstring.h                   | 31 +++++++------------
 xpcom/tests/gtest/TestStrings.cpp             | 12 -------
 7 files changed, 36 insertions(+), 50 deletions(-)

diff --git a/dom/bindings/FakeString.h b/dom/bindings/FakeString.h
index 6fb97208a7aa5..8b34bbc0f6b83 100644
--- a/dom/bindings/FakeString.h
+++ b/dom/bindings/FakeString.h
@@ -85,6 +85,10 @@ struct FakeString {
     return mozilla::Span<const char_type>{mData, Length()};
   }
 
+  operator mozilla::Span<char_type>() {
+    return mozilla::Span{BeginWriting(), Length()};
+  }
+
   mozilla::Result<mozilla::BulkWriteHandle<CharT>, nsresult> BulkWrite(
       size_type aCapacity, size_type aPrefixToPreserve, bool aAllowShrinking) {
     MOZ_ASSERT(!mDataInitialized);
diff --git a/dom/encoding/TextDecoder.cpp b/dom/encoding/TextDecoder.cpp
index 81043a0b450e3..4bf1d0196f885 100644
--- a/dom/encoding/TextDecoder.cpp
+++ b/dom/encoding/TextDecoder.cpp
@@ -54,8 +54,7 @@ void TextDecoder::Decode(Span<const uint8_t> aInput, const bool aStream,
     return;
   }
 
-  auto output = aOutDecodedString.GetMutableData(needed.value(), fallible);
-  if (!output) {
+  if (!aOutDecodedString.SetLength(needed.value(), fallible)) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
@@ -65,15 +64,15 @@ void TextDecoder::Decode(Span<const uint8_t> aInput, const bool aStream,
   size_t written;
   bool hadErrors;
   if (mFatal) {
-    Tie(result, read, written) =
-        mDecoder->DecodeToUTF16WithoutReplacement(aInput, *output, !aStream);
+    Tie(result, read, written) = mDecoder->DecodeToUTF16WithoutReplacement(
+        aInput, aOutDecodedString, !aStream);
     if (result != kInputEmpty) {
       aRv.ThrowTypeError<MSG_DOM_DECODING_FAILED>();
       return;
     }
   } else {
     Tie(result, read, written, hadErrors) =
-        mDecoder->DecodeToUTF16(aInput, *output, !aStream);
+        mDecoder->DecodeToUTF16(aInput, aOutDecodedString, !aStream);
   }
   MOZ_ASSERT(result == kInputEmpty);
   MOZ_ASSERT(read == aInput.Length());
diff --git a/intl/uconv/nsScriptableUConv.cpp b/intl/uconv/nsScriptableUConv.cpp
index d7388403d687d..942da4e7dcd15 100644
--- a/intl/uconv/nsScriptableUConv.cpp
+++ b/intl/uconv/nsScriptableUConv.cpp
@@ -38,13 +38,12 @@ nsScriptableUnicodeConverter::ConvertFromUnicode(const nsAString& aSrc,
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  auto dstChars = _retval.GetMutableData(needed.value(), fallible);
-  if (!dstChars) {
+  if (!_retval.SetLength(needed.value(), fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   auto src = Span(aSrc);
-  auto dst = AsWritableBytes(*dstChars);
+  auto dst = AsWritableBytes(Span(_retval));
   size_t totalWritten = 0;
   for (;;) {
     uint32_t result;
@@ -89,14 +88,13 @@ nsScriptableUnicodeConverter::Finish(nsACString& _retval) {
   // needs to be large enough for an additional NCR,
   // though.
   _retval.SetLength(13);
-  auto dst = AsWritableBytes(_retval.GetMutableData(13));
   Span<char16_t> src(nullptr);
   uint32_t result;
   size_t read;
   size_t written;
   bool hadErrors;
   Tie(result, read, written, hadErrors) =
-      mEncoder->EncodeFromUTF16(src, dst, true);
+      mEncoder->EncodeFromUTF16(src, _retval, true);
   Unused << hadErrors;
   MOZ_ASSERT(!read);
   MOZ_ASSERT(result == kInputEmpty);
@@ -119,8 +117,7 @@ nsScriptableUnicodeConverter::ConvertToUnicode(const nsACString& aSrc,
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  auto dst = _retval.GetMutableData(needed.value(), fallible);
-  if (!dst) {
+  if (!_retval.SetLength(needed.value(), fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
@@ -136,13 +133,13 @@ nsScriptableUnicodeConverter::ConvertToUnicode(const nsACString& aSrc,
   // TextDecoder.
   if (mDecoder->Encoding() == UTF_8_ENCODING) {
     Tie(result, read, written) =
-        mDecoder->DecodeToUTF16WithoutReplacement(src, *dst, false);
+        mDecoder->DecodeToUTF16WithoutReplacement(src, _retval, false);
     if (result != kInputEmpty) {
       return NS_ERROR_UDEC_ILLEGALINPUT;
     }
   } else {
     Tie(result, read, written, hadErrors) =
-        mDecoder->DecodeToUTF16(src, *dst, false);
+        mDecoder->DecodeToUTF16(src, _retval, false);
   }
   MOZ_ASSERT(result == kInputEmpty);
   MOZ_ASSERT(read == length);
diff --git a/mfbt/tests/gtest/TestSpan.cpp b/mfbt/tests/gtest/TestSpan.cpp
index 87dab70027936..a5cd9b9a8d1f4 100644
--- a/mfbt/tests/gtest/TestSpan.cpp
+++ b/mfbt/tests/gtest/TestSpan.cpp
@@ -1057,7 +1057,7 @@ SPAN_TEST(from_xpcom_collections) {
     AssertSpanOfThreeChar16s(str);
     AssertSpanOfThreeChar16sViaString(str);
 
-    Span<char16_t> s{str.GetMutableData()};
+    Span<char16_t> s{str};
     ASSERT_EQ(s.size(), narrow_cast<size_t>(str.Length()));
     ASSERT_EQ(s.data(), str.BeginWriting());
     ASSERT_EQ(s[2], 'c');
@@ -1086,6 +1086,11 @@ SPAN_TEST(from_xpcom_collections) {
     AssertSpanOfThreeChars(str);
     AssertSpanOfThreeCharsViaString(str);
 
+    Span<uint8_t> s{str};
+    ASSERT_EQ(s.size(), narrow_cast<size_t>(str.Length()));
+    ASSERT_EQ(s.data(), reinterpret_cast<uint8_t*>(str.BeginWriting()));
+    ASSERT_EQ(s[2], 'c');
+
     Span<const uint8_t> cs{str};
     ASSERT_EQ(cs.size(), narrow_cast<size_t>(str.Length()));
     ASSERT_EQ(cs.data(), reinterpret_cast<const uint8_t*>(str.BeginReading()));
diff --git a/toolkit/components/osfile/NativeOSFileInternals.cpp b/toolkit/components/osfile/NativeOSFileInternals.cpp
index 157b7a37be8f3..75902e4b774fe 100644
--- a/toolkit/components/osfile/NativeOSFileInternals.cpp
+++ b/toolkit/components/osfile/NativeOSFileInternals.cpp
@@ -835,8 +835,8 @@ class DoReadToStringEvent final : public AbstractReadEvent {
     }
 
     nsString resultString;
-    auto resultSpan = resultString.GetMutableData(needed.value(), fallible);
-    if (!resultSpan) {
+    bool ok = resultString.SetLength(needed.value(), fallible);
+    if (!ok) {
       Fail("allocation"_ns, mResult.forget(), OS_ERROR_TOO_LARGE);
       return;
     }
@@ -849,12 +849,12 @@ class DoReadToStringEvent final : public AbstractReadEvent {
     size_t written;
     bool hadErrors;
     Tie(result, read, written, hadErrors) =
-        mDecoder->DecodeToUTF16(src, *resultSpan, false);
+        mDecoder->DecodeToUTF16(src, resultString, false);
     MOZ_ASSERT(result == kInputEmpty);
     MOZ_ASSERT(read == src.Length());
     MOZ_ASSERT(written <= needed.value());
     Unused << hadErrors;
-    bool ok = resultString.SetLength(written, fallible);
+    ok = resultString.SetLength(written, fallible);
     if (!ok) {
       Fail("allocation"_ns, mResult.forget(), OS_ERROR_TOO_LARGE);
       return;
diff --git a/xpcom/string/nsTSubstring.h b/xpcom/string/nsTSubstring.h
index 0d89b94a74ba2..ecc6330c1ad10 100644
--- a/xpcom/string/nsTSubstring.h
+++ b/xpcom/string/nsTSubstring.h
@@ -15,7 +15,6 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/UniquePtr.h"
-#include "mozilla/Maybe.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/IntegerTypeTraits.h"
 #include "mozilla/Result.h"
@@ -926,28 +925,14 @@ class nsTSubstring : public mozilla::detail::nsTStringRepr<T> {
   }
 #endif
 
-  mozilla::Span<char_type> GetMutableData(size_type aNewLen = size_type(-1)) {
-    if (!EnsureMutable(aNewLen)) {
-      AllocFailed(aNewLen == size_type(-1) ? base_string_type::mLength
-                                           : aNewLen);
-    }
-
-    return mozilla::Span{base_string_type::mData, base_string_type::mLength};
-  }
-
-  mozilla::Maybe<mozilla::Span<char_type>> GetMutableData(size_type aNewLen,
-                                                          const fallible_t&) {
-    if (!EnsureMutable(aNewLen)) {
-      return mozilla::Nothing();
-    }
-    return Some(
-        mozilla::Span{base_string_type::mData, base_string_type::mLength});
-  }
-
   /**
    * Span integration
    */
 
+  operator mozilla::Span<char_type>() {
+    return mozilla::Span{BeginWriting(), base_string_type::Length()};
+  }
+
   operator mozilla::Span<const char_type>() const {
     return mozilla::Span{base_string_type::BeginReading(),
                          base_string_type::Length()};
@@ -980,6 +965,12 @@ class nsTSubstring : public mozilla::detail::nsTStringRepr<T> {
     AppendASCII(aData.Elements(), aData.Length());
   }
 
+  template <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>>
+  operator mozilla::Span<uint8_t>() {
+    return mozilla::Span{reinterpret_cast<uint8_t*>(BeginWriting()),
+                         base_string_type::Length()};
+  }
+
   template <typename Q = T, typename EnableIfChar = mozilla::CharOnlyT<Q>>
   operator mozilla::Span<const uint8_t>() const {
     return mozilla::Span{
@@ -1389,7 +1380,9 @@ static_assert(sizeof(nsTSubstring<char>) ==
  * Span integration
  */
 namespace mozilla {
+Span(nsTSubstring<char>&)->Span<char>;
 Span(const nsTSubstring<char>&)->Span<const char>;
+Span(nsTSubstring<char16_t>&)->Span<char16_t>;
 Span(const nsTSubstring<char16_t>&)->Span<const char16_t>;
 
 }  // namespace mozilla
diff --git a/xpcom/tests/gtest/TestStrings.cpp b/xpcom/tests/gtest/TestStrings.cpp
index d87632dbe70ab..e8e59de5658d9 100644
--- a/xpcom/tests/gtest/TestStrings.cpp
+++ b/xpcom/tests/gtest/TestStrings.cpp
@@ -2018,12 +2018,6 @@ TEST_F(Strings, ConvertToSpan) {
   // from non-const string
   {
     auto span = Span{string};
-    static_assert(std::is_same_v<decltype(span), Span<const char16_t>>);
-  }
-
-  // get mutable data
-  {
-    auto span = string.GetMutableData();
     static_assert(std::is_same_v<decltype(span), Span<char16_t>>);
   }
 
@@ -2040,12 +2034,6 @@ TEST_F(Strings, ConvertToSpan) {
   // from non-const string
   {
     auto span = Span{cstring};
-    static_assert(std::is_same_v<decltype(span), Span<const char>>);
-  }
-
-  // get mutable data
-  {
-    auto span = cstring.GetMutableData();
     static_assert(std::is_same_v<decltype(span), Span<char>>);
   }
 }
-- 
GitLab