Bug 1606958 - Use FakeString for UTF8String. r=bzbarsky

Differential Revision: https://phabricator.services.mozilla.com/D58683

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Emilio Cobos Álvarez 2020-01-06 21:24:10 +00:00
Родитель 0532548244
Коммит ae30f1a7bb
5 изменённых файлов: 81 добавлений и 48 удалений

Просмотреть файл

@ -280,6 +280,7 @@ class Optional<OwningNonNull<T> > : public Optional_base<T, OwningNonNull<T> > {
// ToAStringPtr.
namespace binding_detail {
template <typename CharT>
struct FakeString;
} // namespace binding_detail
@ -297,7 +298,7 @@ class Optional<nsAString> {
// If this code ever goes away, remove the comment pointing to it in the
// FakeString class in BindingUtils.h.
void operator=(const binding_detail::FakeString* str) {
void operator=(const binding_detail::FakeString<nsAString::char_type>* str) {
MOZ_ASSERT(str);
mStr = reinterpret_cast<const nsString*>(str);
}
@ -326,6 +327,14 @@ class Optional<nsACString> {
MOZ_ASSERT(str);
mStr = str;
}
// If this code ever goes away, remove the comment pointing to it in the
// FakeString class in BindingUtils.h.
void operator=(const binding_detail::FakeString<nsACString::char_type>* str) {
MOZ_ASSERT(str);
mStr = reinterpret_cast<const nsCString*>(str);
}
const nsACString& Value() const {
MOZ_ASSERT(WasPassed());
return *mStr;

Просмотреть файл

@ -2541,7 +2541,7 @@ bool NormalizeUSVString(nsAString& aString) {
return EnsureUTF16Validity(aString);
}
bool NormalizeUSVString(binding_detail::FakeString& aString) {
bool NormalizeUSVString(binding_detail::FakeString<char16_t>& aString) {
uint32_t upTo = Utf16ValidUpTo(aString);
uint32_t len = aString.Length();
if (upTo == len) {

Просмотреть файл

@ -1853,7 +1853,8 @@ static inline bool ConvertJSValueToString(JSContext* cx,
MOZ_MUST_USE bool NormalizeUSVString(nsAString& aString);
MOZ_MUST_USE bool NormalizeUSVString(binding_detail::FakeString& aString);
MOZ_MUST_USE bool NormalizeUSVString(
binding_detail::FakeString<char16_t>& aString);
template <typename T>
static inline bool ConvertJSValueToUSVString(JSContext* cx,
@ -2389,29 +2390,34 @@ const T& NonNullHelper(const OwningNonNull<T>& aArg) {
return aArg;
}
inline void NonNullHelper(NonNull<binding_detail::FakeString>& aArg) {
template <typename CharT>
inline void NonNullHelper(NonNull<binding_detail::FakeString<CharT>>& aArg) {
// This overload is here to make sure that we never end up applying
// NonNullHelper to a NonNull<binding_detail::FakeString>. If we
// try to, it should fail to compile, since presumably the caller will try to
// use our nonexistent return value.
}
inline void NonNullHelper(const NonNull<binding_detail::FakeString>& aArg) {
template <typename CharT>
inline void NonNullHelper(
const NonNull<binding_detail::FakeString<CharT>>& aArg) {
// This overload is here to make sure that we never end up applying
// NonNullHelper to a NonNull<binding_detail::FakeString>. If we
// try to, it should fail to compile, since presumably the caller will try to
// use our nonexistent return value.
}
inline void NonNullHelper(binding_detail::FakeString& aArg) {
template <typename CharT>
inline void NonNullHelper(binding_detail::FakeString<CharT>& aArg) {
// This overload is here to make sure that we never end up applying
// NonNullHelper to a FakeString before we've constified it. If we
// try to, it should fail to compile, since presumably the caller will try to
// use our nonexistent return value.
}
MOZ_ALWAYS_INLINE
const nsAString& NonNullHelper(const binding_detail::FakeString& aArg) {
template <typename CharT>
MOZ_ALWAYS_INLINE const nsTSubstring<CharT>& NonNullHelper(
const binding_detail::FakeString<CharT>& aArg) {
return aArg;
}

Просмотреть файл

@ -6013,10 +6013,10 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if isOptional:
if type.isUTF8String():
declType = "Optional<nsACString>"
holderType = CGGeneric("nsAutoCString")
holderType = CGGeneric("binding_detail::FakeString<char>")
else:
declType = "Optional<nsAString>"
holderType = CGGeneric("binding_detail::FakeString")
holderType = CGGeneric("binding_detail::FakeString<char16_t>")
conversionCode = ("%s"
"${declName} = &${holderName};\n" %
getConversionCode("${holderName}"))
@ -6024,9 +6024,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if type.isUTF8String():
# TODO(emilio, bug 1606958): We could make FakeString generic
# if we deem it worth it, instead of using nsAutoCString.
declType = "nsAutoCString"
declType = "binding_detail::FakeString<char>"
else:
declType = "binding_detail::FakeString"
declType = "binding_detail::FakeString<char16_t>"
holderType = None
conversionCode = getConversionCode("${declName}")
@ -10344,7 +10344,10 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
if type.isDOMString() or type.isUSVString():
return CGGeneric("const nsAString&")
if type.isByteString() or type.isUTF8String():
if type.isUTF8String():
return CGGeneric("const nsACString&")
if type.isByteString():
return CGGeneric("const nsCString&")
if type.isEnum():
@ -11761,7 +11764,7 @@ class CGProxyNamedOperation(CGProxySpecialOperation):
decls = ""
idName = "id"
decls += "FakeString %s;\n" % argName
decls += "FakeString<char16_t> %s;\n" % argName
main = fill(
"""

Просмотреть файл

@ -22,15 +22,20 @@ namespace binding_detail {
// point to a literal (static-lifetime) string that's compiled into the binary,
// or point at the buffer of an nsAString whose lifetime is longer than that of
// the FakeString.
template <typename CharT>
struct FakeString {
using char_type = nsString::char_type;
using char_type = CharT;
using string_type = nsTString<CharT>;
using size_type = typename string_type::size_type;
using DataFlags = typename string_type::DataFlags;
using ClassFlags = typename string_type::ClassFlags;
using AString = nsTSubstring<CharT>;
FakeString()
: mDataFlags(nsString::DataFlags::TERMINATED),
mClassFlags(nsString::ClassFlags(0)) {}
: mDataFlags(DataFlags::TERMINATED), mClassFlags(ClassFlags(0)) {}
~FakeString() {
if (mDataFlags & nsString::DataFlags::REFCOUNTED) {
if (mDataFlags & DataFlags::REFCOUNTED) {
MOZ_ASSERT(mDataInitialized);
nsStringBuffer::FromData(mData)->Release();
}
@ -39,24 +44,24 @@ struct FakeString {
// Share aString's string buffer, if it has one; otherwise, make this string
// depend upon aString's data. aString should outlive this instance of
// FakeString.
void ShareOrDependUpon(const nsAString& aString) {
void ShareOrDependUpon(const AString& aString) {
RefPtr<nsStringBuffer> sharedBuffer = nsStringBuffer::FromString(aString);
if (!sharedBuffer) {
InitData(aString.BeginReading(), aString.Length());
if (!aString.IsTerminated()) {
mDataFlags &= ~nsString::DataFlags::TERMINATED;
mDataFlags &= ~DataFlags::TERMINATED;
}
} else {
AssignFromStringBuffer(sharedBuffer.forget(), aString.Length());
}
}
void Truncate() { InitData(nsString::char_traits::sEmptyBuffer, 0); }
void Truncate() { InitData(string_type::char_traits::sEmptyBuffer, 0); }
void SetIsVoid(bool aValue) {
MOZ_ASSERT(aValue, "We don't support SetIsVoid(false) on FakeString!");
Truncate();
mDataFlags |= nsString::DataFlags::VOIDED;
mDataFlags |= DataFlags::VOIDED;
}
char_type* BeginWriting() {
@ -65,7 +70,7 @@ struct FakeString {
return mData;
}
nsString::size_type Length() const { return mLength; }
size_type Length() const { return mLength; }
operator mozilla::Span<const char_type>() const {
MOZ_ASSERT(mDataInitialized);
@ -76,12 +81,23 @@ struct FakeString {
return mozilla::MakeSpan(BeginWriting(), Length());
}
mozilla::BulkWriteHandle<CharT> BulkWrite(size_type aCapacity,
size_type aPrefixToPreserve,
bool aAllowShrinking,
nsresult& aRv) {
MOZ_ASSERT(!mDataInitialized);
InitData(mInlineStorage, 0);
mDataFlags |= DataFlags::INLINE;
return ToAStringPtr()->BulkWrite(aCapacity, aPrefixToPreserve,
aAllowShrinking, aRv);
}
// Reserve space to write aLength chars, not including null-terminator.
bool SetLength(nsString::size_type aLength, mozilla::fallible_t const&) {
bool SetLength(size_type aLength, mozilla::fallible_t const&) {
// Use mInlineStorage for small strings.
if (aLength < sInlineCapacity) {
InitData(mInlineStorage, aLength);
mDataFlags |= nsString::DataFlags::INLINE;
mDataFlags |= DataFlags::INLINE;
} else {
RefPtr<nsStringBuffer> buf =
nsStringBuffer::Alloc((aLength + 1) * sizeof(char_type));
@ -93,7 +109,7 @@ struct FakeString {
}
MOZ_ASSERT(mDataInitialized);
mData[mLength] = char16_t(0);
mData[mLength] = char_type(0);
return true;
}
@ -106,14 +122,14 @@ struct FakeString {
}
RefPtr<nsStringBuffer> buffer;
if (mDataFlags & nsString::DataFlags::REFCOUNTED) {
if (mDataFlags & DataFlags::REFCOUNTED) {
// Make sure we'll drop it when we're done.
buffer = dont_AddRef(nsStringBuffer::FromData(mData));
// And make sure we don't release it twice by accident.
}
const char_type* oldChars = mData;
mDataFlags = nsString::DataFlags::TERMINATED;
mDataFlags = DataFlags::TERMINATED;
#ifdef DEBUG
// Reset mDataInitialized because we're explicitly reinitializing
// it via the SetLength call.
@ -135,7 +151,7 @@ struct FakeString {
void AssignFromStringBuffer(already_AddRefed<nsStringBuffer> aBuffer,
size_t aLength) {
InitData(static_cast<char_type*>(aBuffer.take()->Data()), aLength);
mDataFlags |= nsString::DataFlags::REFCOUNTED;
mDataFlags |= DataFlags::REFCOUNTED;
}
// The preferred way to assign literals to a FakeString. This should only be
@ -151,28 +167,26 @@ struct FakeString {
// from an nsAString that tested true for IsLiteral()).
void AssignLiteral(const char_type* aData, size_t aLength) {
InitData(aData, aLength);
mDataFlags |= nsString::DataFlags::LITERAL;
mDataFlags |= DataFlags::LITERAL;
}
// If this ever changes, change the corresponding code in the
// Optional<nsAString> specialization as well.
const nsAString* ToAStringPtr() const {
return reinterpret_cast<const nsString*>(this);
// Optional<nsA[C]String> specialization as well.
const AString* ToAStringPtr() const {
return reinterpret_cast<const string_type*>(this);
}
operator const nsAString&() const {
return *reinterpret_cast<const nsString*>(this);
}
operator const AString&() const { return *ToAStringPtr(); }
private:
nsAString* ToAStringPtr() { return reinterpret_cast<nsString*>(this); }
AString* ToAStringPtr() { return reinterpret_cast<string_type*>(this); }
// mData is left uninitialized for optimization purposes.
MOZ_INIT_OUTSIDE_CTOR char_type* mData;
// mLength is left uninitialized for optimization purposes.
MOZ_INIT_OUTSIDE_CTOR nsString::size_type mLength;
nsString::DataFlags mDataFlags;
nsString::ClassFlags mClassFlags;
MOZ_INIT_OUTSIDE_CTOR size_type mLength;
DataFlags mDataFlags;
ClassFlags mClassFlags;
static const size_t sInlineCapacity = 64;
char_type mInlineStorage[sInlineCapacity];
@ -183,8 +197,8 @@ struct FakeString {
FakeString(const FakeString& other) = delete;
void operator=(const FakeString& other) = delete;
void InitData(const char_type* aData, nsString::size_type aLength) {
MOZ_ASSERT(mDataFlags == nsString::DataFlags::TERMINATED);
void InitData(const char_type* aData, size_type aLength) {
MOZ_ASSERT(mDataFlags == DataFlags::TERMINATED);
MOZ_ASSERT(!mDataInitialized);
mData = const_cast<char_type*>(aData);
mLength = aLength;
@ -194,22 +208,22 @@ struct FakeString {
}
bool IsMutable() {
return (mDataFlags & nsString::DataFlags::INLINE) ||
((mDataFlags & nsString::DataFlags::REFCOUNTED) &&
return (mDataFlags & DataFlags::INLINE) ||
((mDataFlags & DataFlags::REFCOUNTED) &&
!nsStringBuffer::FromData(mData)->IsReadonly());
}
friend class NonNull<nsAString>;
friend class NonNull<AString>;
// A class to use for our static asserts to ensure our object layout
// matches that of nsString.
class StringAsserter;
friend class StringAsserter;
class StringAsserter : public nsString {
class StringAsserter : public string_type {
public:
static void StaticAsserts() {
static_assert(offsetof(FakeString, mInlineStorage) == sizeof(nsString),
static_assert(offsetof(FakeString, mInlineStorage) == sizeof(string_type),
"FakeString should include all nsString members");
static_assert(
offsetof(FakeString, mData) == offsetof(StringAsserter, mData),
@ -230,9 +244,10 @@ struct FakeString {
} // namespace dom
} // namespace mozilla
template <typename CharT>
inline void AssignFromStringBuffer(
nsStringBuffer* aBuffer, size_t aLength,
mozilla::dom::binding_detail::FakeString& aDest) {
mozilla::dom::binding_detail::FakeString<CharT>& aDest) {
aDest.AssignFromStringBuffer(do_AddRef(aBuffer), aLength);
}