Bug 1892257 - Move nsStringBuffer to mfbt. r=nika,xpcom-reviewers,glandium

Inline Create() and Realloc() so that we don't get negative leaks, since
were that code end up in mozglue, it wouldn't have access to the logging
machinery.

Differential Revision: https://phabricator.services.mozilla.com/D209663
This commit is contained in:
Emilio Cobos Álvarez 2024-05-14 14:24:26 +00:00
parent d691a9d3db
commit d55796be17
45 changed files with 293 additions and 316 deletions

View file

@ -8,7 +8,6 @@
#include "nsString.h" #include "nsString.h"
#include "nsJSPrincipals.h" #include "nsJSPrincipals.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsStringBuffer.h"
#include "mozilla/BasePrincipal.h" #include "mozilla/BasePrincipal.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "mozilla/dom/StructuredCloneTags.h" #include "mozilla/dom/StructuredCloneTags.h"

View file

@ -140,7 +140,7 @@ bool MiscContainer::GetString(nsAString& aString) const {
return false; return false;
} }
if (isString) { if (isString) {
auto* buffer = static_cast<nsStringBuffer*>(ptr); auto* buffer = static_cast<mozilla::StringBuffer*>(ptr);
aString.Assign(buffer, buffer->StorageSize() / sizeof(char16_t) - 1); aString.Assign(buffer, buffer->StorageSize() / sizeof(char16_t) - 1);
} else { } else {
static_cast<nsAtom*>(ptr)->ToString(aString); static_cast<nsAtom*>(ptr)->ToString(aString);
@ -280,7 +280,7 @@ void nsAttrValue::Shutdown() {
void nsAttrValue::Reset() { void nsAttrValue::Reset() {
switch (BaseType()) { switch (BaseType()) {
case eStringBase: { case eStringBase: {
if (auto* str = static_cast<nsStringBuffer*>(GetPtr())) { if (auto* str = static_cast<mozilla::StringBuffer*>(GetPtr())) {
str->Release(); str->Release();
} }
break; break;
@ -318,7 +318,7 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) {
switch (aOther.BaseType()) { switch (aOther.BaseType()) {
case eStringBase: { case eStringBase: {
ResetIfSet(); ResetIfSet();
if (auto* str = static_cast<nsStringBuffer*>(aOther.GetPtr())) { if (auto* str = static_cast<mozilla::StringBuffer*>(aOther.GetPtr())) {
str->AddRef(); str->AddRef();
SetPtrValueAndType(str, eStringBase); SetPtrValueAndType(str, eStringBase);
} }
@ -395,7 +395,7 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) {
bool isString; bool isString;
if (void* otherPtr = otherCont->GetStringOrAtomPtr(isString)) { if (void* otherPtr = otherCont->GetStringOrAtomPtr(isString)) {
if (isString) { if (isString) {
static_cast<nsStringBuffer*>(otherPtr)->AddRef(); static_cast<mozilla::StringBuffer*>(otherPtr)->AddRef();
} else { } else {
static_cast<nsAtom*>(otherPtr)->AddRef(); static_cast<nsAtom*>(otherPtr)->AddRef();
} }
@ -408,7 +408,7 @@ void nsAttrValue::SetTo(const nsAttrValue& aOther) {
void nsAttrValue::SetTo(const nsAString& aValue) { void nsAttrValue::SetTo(const nsAString& aValue) {
ResetIfSet(); ResetIfSet();
nsStringBuffer* buf = GetStringBuffer(aValue).take(); mozilla::StringBuffer* buf = GetStringBuffer(aValue).take();
if (buf) { if (buf) {
SetPtrValueAndType(buf, eStringBase); SetPtrValueAndType(buf, eStringBase);
} }
@ -589,7 +589,7 @@ void nsAttrValue::RemoveDuplicatesFromAtomArray() {
if (void* otherPtr = oldCont->GetStringOrAtomPtr(isString)) { if (void* otherPtr = oldCont->GetStringOrAtomPtr(isString)) {
stringBits = oldCont->mStringBits; stringBits = oldCont->mStringBits;
if (isString) { if (isString) {
static_cast<nsStringBuffer*>(otherPtr)->AddRef(); static_cast<mozilla::StringBuffer*>(otherPtr)->AddRef();
} else { } else {
static_cast<nsAtom*>(otherPtr)->AddRef(); static_cast<nsAtom*>(otherPtr)->AddRef();
} }
@ -620,7 +620,7 @@ void nsAttrValue::ToString(nsAString& aResult) const {
switch (Type()) { switch (Type()) {
case eString: { case eString: {
if (auto* str = static_cast<nsStringBuffer*>(GetPtr())) { if (auto* str = static_cast<mozilla::StringBuffer*>(GetPtr())) {
aResult.Assign(str, str->StorageSize() / sizeof(char16_t) - 1); aResult.Assign(str, str->StorageSize() / sizeof(char16_t) - 1);
} else { } else {
aResult.Truncate(); aResult.Truncate();
@ -770,7 +770,7 @@ already_AddRefed<nsAtom> nsAttrValue::GetAsAtom() const {
const nsCheapString nsAttrValue::GetStringValue() const { const nsCheapString nsAttrValue::GetStringValue() const {
MOZ_ASSERT(Type() == eString, "wrong type"); MOZ_ASSERT(Type() == eString, "wrong type");
return nsCheapString(static_cast<nsStringBuffer*>(GetPtr())); return nsCheapString(static_cast<mozilla::StringBuffer*>(GetPtr()));
} }
bool nsAttrValue::GetColorValue(nscolor& aColor) const { bool nsAttrValue::GetColorValue(nscolor& aColor) const {
@ -890,7 +890,7 @@ nsAtom* nsAttrValue::AtomAt(int32_t aIndex) const {
uint32_t nsAttrValue::HashValue() const { uint32_t nsAttrValue::HashValue() const {
switch (BaseType()) { switch (BaseType()) {
case eStringBase: { case eStringBase: {
if (auto* str = static_cast<nsStringBuffer*>(GetPtr())) { if (auto* str = static_cast<mozilla::StringBuffer*>(GetPtr())) {
uint32_t len = str->StorageSize() / sizeof(char16_t) - 1; uint32_t len = str->StorageSize() / sizeof(char16_t) - 1;
return HashString(static_cast<char16_t*>(str->Data()), len); return HashString(static_cast<char16_t*>(str->Data()), len);
} }
@ -1058,9 +1058,9 @@ bool nsAttrValue::Equals(const nsAttrValue& aOther) const {
(static_cast<ValueBaseType>(otherCont->mStringBits & (static_cast<ValueBaseType>(otherCont->mStringBits &
NS_ATTRVALUE_BASETYPE_MASK) == NS_ATTRVALUE_BASETYPE_MASK) ==
eStringBase)) { eStringBase)) {
return nsCheapString(reinterpret_cast<nsStringBuffer*>( return nsCheapString(reinterpret_cast<mozilla::StringBuffer*>(
static_cast<uintptr_t>(thisCont->mStringBits))) static_cast<uintptr_t>(thisCont->mStringBits)))
.Equals(nsCheapString(reinterpret_cast<nsStringBuffer*>( .Equals(nsCheapString(reinterpret_cast<mozilla::StringBuffer*>(
static_cast<uintptr_t>(otherCont->mStringBits)))); static_cast<uintptr_t>(otherCont->mStringBits))));
} }
} }
@ -1071,7 +1071,7 @@ bool nsAttrValue::Equals(const nsAString& aValue,
nsCaseTreatment aCaseSensitive) const { nsCaseTreatment aCaseSensitive) const {
switch (BaseType()) { switch (BaseType()) {
case eStringBase: { case eStringBase: {
if (auto* str = static_cast<nsStringBuffer*>(GetPtr())) { if (auto* str = static_cast<mozilla::StringBuffer*>(GetPtr())) {
nsDependentString dep(static_cast<char16_t*>(str->Data()), nsDependentString dep(static_cast<char16_t*>(str->Data()),
str->StorageSize() / sizeof(char16_t) - 1); str->StorageSize() / sizeof(char16_t) - 1);
return aCaseSensitive == eCaseMatters return aCaseSensitive == eCaseMatters
@ -1117,7 +1117,7 @@ bool nsAttrValue::Equals(const nsAtom* aValue,
nsDependentAtomString(atom), nsDependentAtomString(aValue)); nsDependentAtomString(atom), nsDependentAtomString(aValue));
} }
case eStringBase: { case eStringBase: {
if (auto* str = static_cast<nsStringBuffer*>(GetPtr())) { if (auto* str = static_cast<mozilla::StringBuffer*>(GetPtr())) {
size_t strLen = str->StorageSize() / sizeof(char16_t) - 1; size_t strLen = str->StorageSize() / sizeof(char16_t) - 1;
if (aValue->GetLength() != strLen) { if (aValue->GetLength() != strLen) {
return false; return false;
@ -1202,7 +1202,7 @@ bool nsAttrValue::SubstringCheck(const nsAString& aValue,
nsCaseTreatment aCaseSensitive) const { nsCaseTreatment aCaseSensitive) const {
switch (BaseType()) { switch (BaseType()) {
case eStringBase: { case eStringBase: {
if (auto* str = static_cast<nsStringBuffer*>(GetPtr())) { if (auto* str = static_cast<mozilla::StringBuffer*>(GetPtr())) {
return F::Check(static_cast<char16_t*>(str->Data()), return F::Check(static_cast<char16_t*>(str->Data()),
str->StorageSize() / sizeof(char16_t) - 1, aValue, str->StorageSize() / sizeof(char16_t) - 1, aValue,
aCaseSensitive); aCaseSensitive);
@ -1518,9 +1518,9 @@ nsAtom* nsAttrValue::GetStoredAtom() const {
return nullptr; return nullptr;
} }
nsStringBuffer* nsAttrValue::GetStoredStringBuffer() const { mozilla::StringBuffer* nsAttrValue::GetStoredStringBuffer() const {
if (BaseType() == eStringBase) { if (BaseType() == eStringBase) {
return static_cast<nsStringBuffer*>(GetPtr()); return static_cast<mozilla::StringBuffer*>(GetPtr());
} }
if (BaseType() == eOtherBase) { if (BaseType() == eOtherBase) {
return GetMiscContainer()->GetStoredStringBuffer(); return GetMiscContainer()->GetStoredStringBuffer();
@ -1829,7 +1829,7 @@ bool nsAttrValue::ParsePositiveIntValue(const nsAString& aString) {
} }
void nsAttrValue::SetColorValue(nscolor aColor, const nsAString& aString) { void nsAttrValue::SetColorValue(nscolor aColor, const nsAString& aString) {
nsStringBuffer* buf = GetStringBuffer(aString).take(); mozilla::StringBuffer* buf = GetStringBuffer(aString).take();
if (!buf) { if (!buf) {
return; return;
} }
@ -1988,7 +1988,7 @@ void nsAttrValue::SetMiscAtomOrString(const nsAString* aValue) {
atom->Release(); atom->Release();
} }
} else { } else {
nsStringBuffer* buffer = GetStringBuffer(*aValue).take(); mozilla::StringBuffer* buffer = GetStringBuffer(*aValue).take();
NS_ENSURE_TRUE_VOID(buffer); NS_ENSURE_TRUE_VOID(buffer);
uintptr_t bits = reinterpret_cast<uintptr_t>(buffer) | eStringBase; uintptr_t bits = reinterpret_cast<uintptr_t>(buffer) | eStringBase;
@ -2009,7 +2009,7 @@ void nsAttrValue::ResetMiscAtomOrString() {
bool isString; bool isString;
if (void* ptr = cont->GetStringOrAtomPtr(isString)) { if (void* ptr = cont->GetStringOrAtomPtr(isString)) {
if (isString) { if (isString) {
static_cast<nsStringBuffer*>(ptr)->Release(); static_cast<mozilla::StringBuffer*>(ptr)->Release();
} else { } else {
static_cast<nsAtom*>(ptr)->Release(); static_cast<nsAtom*>(ptr)->Release();
} }
@ -2094,19 +2094,19 @@ MiscContainer* nsAttrValue::EnsureEmptyMiscContainer() {
return cont; return cont;
} }
already_AddRefed<nsStringBuffer> nsAttrValue::GetStringBuffer( already_AddRefed<mozilla::StringBuffer> nsAttrValue::GetStringBuffer(
const nsAString& aValue) const { const nsAString& aValue) const {
uint32_t len = aValue.Length(); uint32_t len = aValue.Length();
if (!len) { if (!len) {
return nullptr; return nullptr;
} }
if (nsStringBuffer* buf = aValue.GetStringBuffer(); if (mozilla::StringBuffer* buf = aValue.GetStringBuffer();
buf && (buf->StorageSize() / sizeof(char16_t) - 1) == len) { buf && (buf->StorageSize() / sizeof(char16_t) - 1) == len) {
// We can only reuse the buffer if it's exactly sized, since we rely on // We can only reuse the buffer if it's exactly sized, since we rely on
// StorageSize() to get the string length in ToString(). // StorageSize() to get the string length in ToString().
return do_AddRef(buf); return do_AddRef(buf);
} }
return nsStringBuffer::Create(aValue.Data(), aValue.Length()); return mozilla::StringBuffer::Create(aValue.Data(), aValue.Length());
} }
size_t nsAttrValue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const { size_t nsAttrValue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
@ -2114,7 +2114,8 @@ size_t nsAttrValue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
switch (BaseType()) { switch (BaseType()) {
case eStringBase: { case eStringBase: {
nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr()); mozilla::StringBuffer* str =
static_cast<mozilla::StringBuffer*>(GetPtr());
n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0; n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0;
break; break;
} }
@ -2134,7 +2135,7 @@ size_t nsAttrValue::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
// We only count the size of the object pointed by otherPtr if it's a // We only count the size of the object pointed by otherPtr if it's a
// string. When it's an atom, it's counted separatly. // string. When it's an atom, it's counted separatly.
if (nsStringBuffer* buf = container->GetStoredStringBuffer()) { if (mozilla::StringBuffer* buf = container->GetStoredStringBuffer()) {
n += buf->SizeOfIncludingThisIfUnshared(aMallocSizeOf); n += buf->SizeOfIncludingThisIfUnshared(aMallocSizeOf);
} }

View file

@ -16,7 +16,7 @@
#include "nscore.h" #include "nscore.h"
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h" #include "mozilla/StringBuffer.h"
#include "nsColor.h" #include "nsColor.h"
#include "nsCaseTreatment.h" #include "nsCaseTreatment.h"
#include "nsMargin.h" #include "nsMargin.h"
@ -95,19 +95,19 @@ const uintptr_t NS_ATTRVALUE_BASETYPE_MASK = 3;
~NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER))) ~NS_ATTRVALUE_ENUMTABLE_VALUE_NEEDS_TO_UPPER)))
/** /**
* A class used to construct a nsString from a nsStringBuffer (we might * A class used to construct a nsString from a mozilla::StringBuffer (we might
* want to move this to nsString at some point). * want to move this to nsString at some point).
* *
* WARNING: Note that nsCheapString doesn't take an explicit length -- it * WARNING: Note that nsCheapString doesn't take an explicit length -- it
* assumes the string is maximally large, given the nsStringBuffer's storage * assumes the string is maximally large, given the mozilla::StringBuffer's
* size. This means the given string buffer *must* be sized exactly correctly * storage size. This means the given string buffer *must* be sized exactly
* for the string it contains (including one byte for a null terminator). If * correctly for the string it contains (including one byte for a null
* it has any unused storage space, then that will result in bogus characters * terminator). If it has any unused storage space, then that will result in
* at the end of our nsCheapString. * bogus characters at the end of our nsCheapString.
*/ */
class nsCheapString : public nsString { class nsCheapString : public nsString {
public: public:
explicit nsCheapString(nsStringBuffer* aBuf) { explicit nsCheapString(mozilla::StringBuffer* aBuf) {
if (aBuf) { if (aBuf) {
Assign(aBuf, aBuf->StorageSize() / sizeof(char16_t) - 1); Assign(aBuf, aBuf->StorageSize() / sizeof(char16_t) - 1);
} }
@ -486,7 +486,7 @@ class nsAttrValue {
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
nsAtom* GetStoredAtom() const; nsAtom* GetStoredAtom() const;
nsStringBuffer* GetStoredStringBuffer() const; mozilla::StringBuffer* GetStoredStringBuffer() const;
private: private:
// These have to be the same as in ValueType // These have to be the same as in ValueType
@ -532,7 +532,7 @@ class nsAttrValue {
// Like ClearMiscContainer, except allocates a new container if one does not // Like ClearMiscContainer, except allocates a new container if one does not
// exist already. // exist already.
MiscContainer* EnsureEmptyMiscContainer(); MiscContainer* EnsureEmptyMiscContainer();
already_AddRefed<nsStringBuffer> GetStringBuffer( already_AddRefed<mozilla::StringBuffer> GetStringBuffer(
const nsAString& aValue) const; const nsAString& aValue) const;
// Given an enum table and a particular entry in that table, return // Given an enum table and a particular entry in that table, return
// the actual integer value we should store. // the actual integer value we should store.

View file

@ -23,10 +23,9 @@ struct MiscContainer final {
using ValueType = nsAttrValue::ValueType; using ValueType = nsAttrValue::ValueType;
ValueType mType; ValueType mType;
// mStringBits points to either nsAtom* or nsStringBuffer* and is used when // mStringBits points to either nsAtom* or mozilla::StringBuffer* and is used
// mType isn't eCSSDeclaration. // when mType isn't eCSSDeclaration. Note eStringBase and eAtomBase is used
// Note eStringBase and eAtomBase is used also to handle the type of // also to handle the type of mStringBits.
// mStringBits.
// //
// Note that we use an atomic here so that we can use Compare-And-Swap // Note that we use an atomic here so that we can use Compare-And-Swap
// to cache the serialization during the parallel servo traversal. This case // to cache the serialization during the parallel servo traversal. This case
@ -102,10 +101,10 @@ struct MiscContainer final {
return isString ? nullptr : static_cast<nsAtom*>(ptr); return isString ? nullptr : static_cast<nsAtom*>(ptr);
} }
nsStringBuffer* GetStoredStringBuffer() const { mozilla::StringBuffer* GetStoredStringBuffer() const {
bool isString = false; bool isString = false;
void* ptr = GetStringOrAtomPtr(isString); void* ptr = GetStringOrAtomPtr(isString);
return isString ? static_cast<nsStringBuffer*>(ptr) : nullptr; return isString ? static_cast<mozilla::StringBuffer*>(ptr) : nullptr;
} }
void SetStringBitsMainThread(uintptr_t aBits) { void SetStringBitsMainThread(uintptr_t aBits) {
@ -247,8 +246,7 @@ inline nsAtom* nsAttrValue::GetAtomValue() const {
inline void nsAttrValue::ToString(mozilla::dom::DOMString& aResult) const { inline void nsAttrValue::ToString(mozilla::dom::DOMString& aResult) const {
switch (Type()) { switch (Type()) {
case eString: { case eString: {
nsStringBuffer* str = static_cast<nsStringBuffer*>(GetPtr()); if (auto* str = static_cast<mozilla::StringBuffer*>(GetPtr())) {
if (str) {
aResult.SetKnownLiveStringBuffer( aResult.SetKnownLiveStringBuffer(
str, str->StorageSize() / sizeof(char16_t) - 1); str, str->StorageSize() / sizeof(char16_t) - 1);
} }

View file

@ -369,7 +369,6 @@
#include "nsServiceManagerUtils.h" #include "nsServiceManagerUtils.h"
#include "nsStreamUtils.h" #include "nsStreamUtils.h"
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h"
#include "nsStringBundle.h" #include "nsStringBundle.h"
#include "nsStringFlags.h" #include "nsStringFlags.h"
#include "nsStringFwd.h" #include "nsStringFwd.h"

View file

@ -142,6 +142,7 @@ class HTMLEditor;
class LazyLogModule; class LazyLogModule;
class LogModule; class LogModule;
class PresShell; class PresShell;
class StringBuffer;
class TextEditor; class TextEditor;
class WidgetDragEvent; class WidgetDragEvent;
class WidgetKeyboardEvent; class WidgetKeyboardEvent;

View file

@ -106,7 +106,7 @@ nsTextFragment& nsTextFragment::operator=(const nsTextFragment& aOther) {
memcpy(const_cast<char*>(m1b), aOther.m1b, aOther.mState.mLength); memcpy(const_cast<char*>(m1b), aOther.m1b, aOther.mState.mLength);
} else { } else {
// allocate a buffer for a single REPLACEMENT CHARACTER // allocate a buffer for a single REPLACEMENT CHARACTER
m2b = nsStringBuffer::Alloc(sizeof(char16_t) * 2).take(); m2b = StringBuffer::Alloc(sizeof(char16_t) * 2).take();
if (!m2b) { if (!m2b) {
MOZ_CRASH("OOM!"); MOZ_CRASH("OOM!");
} }
@ -202,7 +202,7 @@ bool nsTextFragment::SetTo(const char16_t* aBuffer, uint32_t aLength,
uint32_t neededSize = aLength * sizeof(char16_t); uint32_t neededSize = aLength * sizeof(char16_t);
if (!neededSize) { if (!neededSize) {
if (storageSize < AutoStringDefaultStorageSize) { if (storageSize < AutoStringDefaultStorageSize) {
// If we're storing small enough nsStringBuffer, let's preserve it. // If we're storing small enough StringBuffer, let's preserve it.
static_cast<char16_t*>(m2b->Data())[0] = char16_t(0); static_cast<char16_t*>(m2b->Data())[0] = char16_t(0);
mState.mLength = 0; mState.mLength = 0;
@ -212,7 +212,7 @@ bool nsTextFragment::SetTo(const char16_t* aBuffer, uint32_t aLength,
} else if ((neededSize < storageSize) && } else if ((neededSize < storageSize) &&
((storageSize / 2) < ((storageSize / 2) <
(neededSize + AutoStringDefaultStorageSize))) { (neededSize + AutoStringDefaultStorageSize))) {
// Don't try to reuse the existing nsStringBuffer, if it would have // Don't try to reuse the existing StringBuffer, if it would have
// lots of unused space. // lots of unused space.
memcpy(m2b->Data(), aBuffer, neededSize); memcpy(m2b->Data(), aBuffer, neededSize);
@ -296,7 +296,7 @@ bool nsTextFragment::SetTo(const char16_t* aBuffer, uint32_t aLength,
return false; return false;
} }
m2b = nsStringBuffer::Alloc(m2bSize.value()).take(); m2b = StringBuffer::Alloc(m2bSize.value()).take();
if (!m2b) { if (!m2b) {
return false; return false;
} }
@ -373,10 +373,10 @@ bool nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength,
size *= sizeof(char16_t); size *= sizeof(char16_t);
// Already a 2-byte string so the result will be too // Already a 2-byte string so the result will be too
nsStringBuffer* buff = nullptr; StringBuffer* buff = nullptr;
nsStringBuffer* bufferToRelease = nullptr; StringBuffer* bufferToRelease = nullptr;
if (m2b->IsReadonly()) { if (m2b->IsReadonly()) {
buff = nsStringBuffer::Alloc(size).take(); buff = StringBuffer::Alloc(size).take();
if (!buff) { if (!buff) {
return false; return false;
} }
@ -384,7 +384,7 @@ bool nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength,
memcpy(static_cast<char16_t*>(buff->Data()), m2b->Data(), memcpy(static_cast<char16_t*>(buff->Data()), m2b->Data(),
mState.mLength * sizeof(char16_t)); mState.mLength * sizeof(char16_t));
} else { } else {
buff = nsStringBuffer::Realloc(m2b, size); buff = StringBuffer::Realloc(m2b, size);
if (!buff) { if (!buff) {
return false; return false;
} }
@ -418,7 +418,7 @@ bool nsTextFragment::Append(const char16_t* aBuffer, uint32_t aLength,
// The old data was 1-byte, but the new is not so we have to expand it // The old data was 1-byte, but the new is not so we have to expand it
// all to 2-byte // all to 2-byte
nsStringBuffer* buff = nsStringBuffer::Alloc(size).take(); StringBuffer* buff = StringBuffer::Alloc(size).take();
if (!buff) { if (!buff) {
return false; return false;
} }

View file

@ -18,7 +18,7 @@
#include "nsCharTraits.h" #include "nsCharTraits.h"
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h" #include "mozilla/StringBuffer.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "nsISupportsImpl.h" #include "nsISupportsImpl.h"
@ -113,7 +113,7 @@ class nsTextFragment final {
} }
ReleaseText(); ReleaseText();
if (aForce2b && !aUpdateBidi) { if (aForce2b && !aUpdateBidi) {
if (nsStringBuffer* buffer = aString.GetStringBuffer()) { if (mozilla::StringBuffer* buffer = aString.GetStringBuffer()) {
NS_ADDREF(m2b = buffer); NS_ADDREF(m2b = buffer);
mState.mInHeap = true; mState.mInHeap = true;
mState.mIs2b = true; mState.mIs2b = true;
@ -296,7 +296,7 @@ class nsTextFragment final {
void UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength); void UpdateBidiFlag(const char16_t* aBuffer, uint32_t aLength);
union { union {
nsStringBuffer* m2b; mozilla::StringBuffer* m2b;
const char* m1b; // This is const since it can point to shared data const char* m1b; // This is const since it can point to shared data
}; };

View file

@ -8,10 +8,10 @@
#define mozilla_dom_DOMString_h #define mozilla_dom_DOMString_h
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/Attributes.h" #include "mozilla/Attributes.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "mozilla/StringBuffer.h"
#include "nsDOMString.h" #include "nsDOMString.h"
#include "nsAtom.h" #include "nsAtom.h"
@ -36,10 +36,10 @@ namespace mozilla::dom {
* It's only OK to call * It's only OK to call
* SetKnownLiveStringBuffer/SetKnownLiveString/SetKnownLiveAtom if the caller of * SetKnownLiveStringBuffer/SetKnownLiveString/SetKnownLiveAtom if the caller of
* the method in question plans to keep holding a strong ref to the stringbuffer * the method in question plans to keep holding a strong ref to the stringbuffer
* involved, whether it's a raw nsStringBuffer, or stored inside the string or * involved, whether it's a raw mozilla::StringBuffer, or stored inside the
* atom being passed. In the string/atom cases that means the caller must own * string or atom being passed. In the string/atom cases that means the caller
* the string or atom, and not mutate it (in the string case) for the lifetime * must own the string or atom, and not mutate it (in the string case) for the
* of the DOMString. * lifetime of the DOMString.
* *
* The proper way to extract a value is to check IsNull(). If not null, then * The proper way to extract a value is to check IsNull(). If not null, then
* check IsEmpty(). If neither of those is true, check HasStringBuffer(). If * check IsEmpty(). If neither of those is true, check HasStringBuffer(). If
@ -86,9 +86,9 @@ class MOZ_STACK_CLASS DOMString {
// Get the stringbuffer. This can only be called if HasStringBuffer() // Get the stringbuffer. This can only be called if HasStringBuffer()
// returned true. If that's true, it will never return null. Note that // returned true. If that's true, it will never return null. Note that
// constructing a string from this nsStringBuffer with length given by // constructing a string from this mozilla::StringBuffer with length given by
// StringBufferLength() might give you something that is not null-terminated. // StringBufferLength() might give you something that is not null-terminated.
nsStringBuffer* StringBuffer() const { mozilla::StringBuffer* StringBuffer() const {
MOZ_ASSERT(HasStringBuffer(), MOZ_ASSERT(HasStringBuffer(),
"Don't ask for the stringbuffer if we don't have it"); "Don't ask for the stringbuffer if we don't have it");
MOZ_ASSERT(mStringBuffer, "We better have a stringbuffer if we claim to"); MOZ_ASSERT(mStringBuffer, "We better have a stringbuffer if we claim to");
@ -103,8 +103,8 @@ class MOZ_STACK_CLASS DOMString {
return mLength; return mLength;
} }
// Tell the DOMString to relinquish ownership of its nsStringBuffer to the // Tell the DOMString to relinquish ownership of its mozilla::StringBuffer to
// caller. Can only be called if HasStringBuffer(). // the caller. Can only be called if HasStringBuffer().
void RelinquishBufferOwnership() { void RelinquishBufferOwnership() {
MOZ_ASSERT(HasStringBuffer(), MOZ_ASSERT(HasStringBuffer(),
"Don't call this if there is no stringbuffer"); "Don't call this if there is no stringbuffer");
@ -138,10 +138,10 @@ class MOZ_STACK_CLASS DOMString {
return mLength; return mLength;
} }
// Initialize the DOMString to a (nsStringBuffer, length) pair. The length // Initialize the DOMString to a (mozilla::StringBuffer, length) pair. The
// does NOT have to be the full length of the (null-terminated) string in the // length does NOT have to be the full length of the (null-terminated) string
// nsStringBuffer. // in the mozilla::StringBuffer.
void SetKnownLiveStringBuffer(nsStringBuffer* aStringBuffer, void SetKnownLiveStringBuffer(mozilla::StringBuffer* aStringBuffer,
uint32_t aLength) { uint32_t aLength) {
MOZ_ASSERT(mState == State::Empty, "We're already set to a value"); MOZ_ASSERT(mState == State::Empty, "We're already set to a value");
if (aLength != 0) { if (aLength != 0) {
@ -151,8 +151,9 @@ class MOZ_STACK_CLASS DOMString {
// else nothing to do // else nothing to do
} }
// Like SetKnownLiveStringBuffer, but holds a reference to the nsStringBuffer. // Like SetKnownLiveStringBuffer, but holds a reference to the
void SetStringBuffer(nsStringBuffer* aStringBuffer, uint32_t aLength) { // mozilla::StringBuffer.
void SetStringBuffer(mozilla::StringBuffer* aStringBuffer, uint32_t aLength) {
MOZ_ASSERT(mState == State::Empty, "We're already set to a value"); MOZ_ASSERT(mState == State::Empty, "We're already set to a value");
if (aLength != 0) { if (aLength != 0) {
SetStringBufferInternal(aStringBuffer, aLength); SetStringBufferInternal(aStringBuffer, aLength);
@ -169,7 +170,7 @@ class MOZ_STACK_CLASS DOMString {
if (MOZ_UNLIKELY(aString.IsVoid())) { if (MOZ_UNLIKELY(aString.IsVoid())) {
SetNull(); SetNull();
} else if (!aString.IsEmpty()) { } else if (!aString.IsEmpty()) {
if (nsStringBuffer* buf = aString.GetStringBuffer()) { if (mozilla::StringBuffer* buf = aString.GetStringBuffer()) {
SetKnownLiveStringBuffer(buf, aString.Length()); SetKnownLiveStringBuffer(buf, aString.Length());
} else if (aString.IsLiteral()) { } else if (aString.IsLiteral()) {
SetLiteralInternal(aString.BeginReading(), aString.Length()); SetLiteralInternal(aString.BeginReading(), aString.Length());
@ -228,9 +229,9 @@ class MOZ_STACK_CLASS DOMString {
} else if (IsEmpty()) { } else if (IsEmpty()) {
aString.Truncate(); aString.Truncate();
} else if (HasStringBuffer()) { } else if (HasStringBuffer()) {
// Don't share the nsStringBuffer with aString if the result would not // Don't share the mozilla::StringBuffer with aString if the result would
// be null-terminated. // not be null-terminated.
nsStringBuffer* buf = StringBuffer(); mozilla::StringBuffer* buf = StringBuffer();
uint32_t len = StringBufferLength(); uint32_t len = StringBufferLength();
auto chars = static_cast<char16_t*>(buf->Data()); auto chars = static_cast<char16_t*>(buf->Data());
if (chars[len] == '\0') { if (chars[len] == '\0') {
@ -248,7 +249,7 @@ class MOZ_STACK_CLASS DOMString {
} }
private: private:
void SetStringBufferInternal(nsStringBuffer* aStringBuffer, void SetStringBufferInternal(mozilla::StringBuffer* aStringBuffer,
uint32_t aLength) { uint32_t aLength) {
MOZ_ASSERT(mString.isNothing(), "We already have a string?"); MOZ_ASSERT(mString.isNothing(), "We already have a string?");
MOZ_ASSERT(mState == State::Empty, "We're already set to a value"); MOZ_ASSERT(mState == State::Empty, "We're already set to a value");
@ -285,8 +286,9 @@ class MOZ_STACK_CLASS DOMString {
Maybe<nsAutoString> mString; Maybe<nsAutoString> mString;
union { union {
// The nsStringBuffer in the OwnedStringBuffer/UnownedStringBuffer cases. // The mozilla::StringBuffer in the OwnedStringBuffer/UnownedStringBuffer
nsStringBuffer* MOZ_UNSAFE_REF( // cases.
mozilla::StringBuffer* MOZ_UNSAFE_REF(
"The ways in which this can be safe are " "The ways in which this can be safe are "
"documented above and enforced through " "documented above and enforced through "
"assertions") mStringBuffer; "assertions") mStringBuffer;

View file

@ -8,7 +8,7 @@
#define mozilla_dom_FakeString_h__ #define mozilla_dom_FakeString_h__
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h" #include "mozilla/StringBuffer.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
#include "mozilla/Span.h" #include "mozilla/Span.h"
#include "js/String.h" #include "js/String.h"
@ -18,7 +18,7 @@ namespace mozilla::dom::binding_detail {
// A struct that has a layout compatible with nsAString, so that // A struct that has a layout compatible with nsAString, so that
// reinterpret-casting a FakeString as a const nsAString is safe, but much // reinterpret-casting a FakeString as a const nsAString is safe, but much
// faster constructor and destructor behavior. FakeString uses inline storage // faster constructor and destructor behavior. FakeString uses inline storage
// for small strings and an nsStringBuffer for longer strings. It can also // for small strings and an StringBuffer for longer strings. It can also
// point to a literal (static-lifetime) string that's compiled into the binary, // 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 // or point at the buffer of an nsAString whose lifetime is longer than that of
// the FakeString. // the FakeString.
@ -43,7 +43,7 @@ struct FakeString {
~FakeString() { ~FakeString() {
if (mDataFlags & DataFlags::REFCOUNTED) { if (mDataFlags & DataFlags::REFCOUNTED) {
MOZ_ASSERT(mDataInitialized); MOZ_ASSERT(mDataInitialized);
nsStringBuffer::FromData(mData)->Release(); StringBuffer::FromData(mData)->Release();
} }
} }
@ -51,7 +51,7 @@ struct FakeString {
// depend upon aString's data. aString should outlive this instance of // depend upon aString's data. aString should outlive this instance of
// FakeString. // FakeString.
void ShareOrDependUpon(const AString& aString) { void ShareOrDependUpon(const AString& aString) {
RefPtr<nsStringBuffer> sharedBuffer = aString.GetStringBuffer(); RefPtr<StringBuffer> sharedBuffer = aString.GetStringBuffer();
if (!sharedBuffer) { if (!sharedBuffer) {
InitData(aString.BeginReading(), aString.Length()); InitData(aString.BeginReading(), aString.Length());
if (!aString.IsTerminated()) { if (!aString.IsTerminated()) {
@ -102,8 +102,8 @@ struct FakeString {
InitData(mStorage, aLength); InitData(mStorage, aLength);
mDataFlags |= DataFlags::INLINE; mDataFlags |= DataFlags::INLINE;
} else { } else {
RefPtr<nsStringBuffer> buf = RefPtr<StringBuffer> buf =
nsStringBuffer::Alloc((aLength + 1) * sizeof(char_type)); StringBuffer::Alloc((aLength + 1) * sizeof(char_type));
if (MOZ_UNLIKELY(!buf)) { if (MOZ_UNLIKELY(!buf)) {
return false; return false;
} }
@ -124,10 +124,10 @@ struct FakeString {
return true; return true;
} }
RefPtr<nsStringBuffer> buffer; RefPtr<StringBuffer> buffer;
if (mDataFlags & DataFlags::REFCOUNTED) { if (mDataFlags & DataFlags::REFCOUNTED) {
// Make sure we'll drop it when we're done. // Make sure we'll drop it when we're done.
buffer = dont_AddRef(nsStringBuffer::FromData(mData)); buffer = dont_AddRef(StringBuffer::FromData(mData));
// And make sure we don't release it twice by accident. // And make sure we don't release it twice by accident.
} }
const char_type* oldChars = mData; const char_type* oldChars = mData;
@ -151,7 +151,7 @@ struct FakeString {
return true; return true;
} }
void AssignFromStringBuffer(already_AddRefed<nsStringBuffer> aBuffer, void AssignFromStringBuffer(already_AddRefed<StringBuffer> aBuffer,
size_t aLength) { size_t aLength) {
InitData(static_cast<char_type*>(aBuffer.take()->Data()), aLength); InitData(static_cast<char_type*>(aBuffer.take()->Data()), aLength);
mDataFlags |= DataFlags::REFCOUNTED; mDataFlags |= DataFlags::REFCOUNTED;
@ -214,7 +214,7 @@ struct FakeString {
bool IsMutable() { bool IsMutable() {
return (mDataFlags & DataFlags::INLINE) || return (mDataFlags & DataFlags::INLINE) ||
((mDataFlags & DataFlags::REFCOUNTED) && ((mDataFlags & DataFlags::REFCOUNTED) &&
!nsStringBuffer::FromData(mData)->IsReadonly()); !StringBuffer::FromData(mData)->IsReadonly());
} }
friend class NonNull<AString>; friend class NonNull<AString>;
@ -257,11 +257,15 @@ struct FakeString {
}; };
} // namespace mozilla::dom::binding_detail } // namespace mozilla::dom::binding_detail
namespace mozilla {
template <typename CharT> template <typename CharT>
inline void AssignFromStringBuffer( inline void AssignFromStringBuffer(
nsStringBuffer* aBuffer, size_t aLength, StringBuffer* aBuffer, size_t aLength,
mozilla::dom::binding_detail::FakeString<CharT>& aDest) { dom::binding_detail::FakeString<CharT>& aDest) {
aDest.AssignFromStringBuffer(do_AddRef(aBuffer), aLength); aDest.AssignFromStringBuffer(do_AddRef(aBuffer), aLength);
} }
} // namespace mozilla
#endif /* mozilla_dom_FakeString_h__ */ #endif /* mozilla_dom_FakeString_h__ */

View file

@ -11,7 +11,7 @@
#include "mozilla/dom/WindowProxyHolder.h" #include "mozilla/dom/WindowProxyHolder.h"
#include "nsAString.h" #include "nsAString.h"
#include "nsContentUtils.h" #include "nsContentUtils.h"
#include "nsStringBuffer.h" #include "mozilla/StringBuffer.h"
#include "xpcpublic.h" #include "xpcpublic.h"
namespace mozilla::dom { namespace mozilla::dom {
@ -23,7 +23,7 @@ bool ToJSValue(JSContext* aCx, const nsAString& aArgument,
// XXXkhuey I'd love to use xpc::NonVoidStringToJsval here, but it requires // XXXkhuey I'd love to use xpc::NonVoidStringToJsval here, but it requires
// a non-const nsAString for silly reasons. // a non-const nsAString for silly reasons.
nsStringBuffer* sharedBuffer; mozilla::StringBuffer* sharedBuffer;
if (!XPCStringConvert::ReadableToJSVal(aCx, aArgument, &sharedBuffer, if (!XPCStringConvert::ReadableToJSVal(aCx, aArgument, &sharedBuffer,
aValue)) { aValue)) {
return false; return false;

View file

@ -10,7 +10,7 @@
#include "mozilla/dom/TestFunctionsBinding.h" #include "mozilla/dom/TestFunctionsBinding.h"
#include "mozilla/dom/WindowBinding.h" #include "mozilla/dom/WindowBinding.h"
#include "mozilla/dom/WrapperCachedNonISupportsTestInterface.h" #include "mozilla/dom/WrapperCachedNonISupportsTestInterface.h"
#include "nsStringBuffer.h" #include "mozilla/StringBuffer.h"
#include "mozITestInterfaceJS.h" #include "mozITestInterfaceJS.h"
#include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h"
#include "nsGlobalWindowInner.h" #include "nsGlobalWindowInner.h"
@ -66,7 +66,7 @@ void TestFunctions::GetStringDataAsDOMString(const Optional<uint32_t>& aLength,
length = mStringData.Length(); length = mStringData.Length();
} }
if (nsStringBuffer* buf = mStringData.GetStringBuffer()) { if (StringBuffer* buf = mStringData.GetStringBuffer()) {
aString.SetKnownLiveStringBuffer(buf, length); aString.SetKnownLiveStringBuffer(buf, length);
return; return;
} }

View file

@ -1999,13 +1999,13 @@ and exported to `mozilla/dom/BindingDeclarations.h` that is used for
Web IDL `DOMString` return values. It has a conversion operator to Web IDL `DOMString` return values. It has a conversion operator to
`nsString&` so that it can be passed to methods that take that type or `nsString&` so that it can be passed to methods that take that type or
`nsAString&`, but callees that care about performance, have an `nsAString&`, but callees that care about performance, have an
`nsStringBuffer` available, and promise to hold on to the `StringBuffer` available, and promise to hold on to the
`nsStringBuffer` at least until the binding code comes off the stack `StringBuffer` at least until the binding code comes off the stack
can also take a `DOMString` directly for their string return value and can also take a `DOMString` directly for their string return value and
call its `SetStringBuffer` method with the `nsStringBuffer` and its call its `SetStringBuffer` method with the `StringBuffer` and its
length. This allows the binding code to avoid extra reference-counting length. This allows the binding code to avoid extra reference-counting
of the string buffer in many cases, and allows it to take a faster of the string buffer in many cases, and allows it to take a faster
codepath even if it does end up having to addref the `nsStringBuffer`. codepath even if it does end up having to addref the `StringBuffer`.
### `GlobalObject` ### `GlobalObject`

View file

@ -1068,8 +1068,8 @@ already_AddRefed<nsITransferable> DataTransfer::GetTransferable(
nsCOMPtr<nsIInputStream> inputStream; nsCOMPtr<nsIInputStream> inputStream;
storageStream->NewInputStream(0, getter_AddRefs(inputStream)); storageStream->NewInputStream(0, getter_AddRefs(inputStream));
RefPtr<nsStringBuffer> stringBuffer = RefPtr<StringBuffer> stringBuffer =
nsStringBuffer::Alloc(totalCustomLength); StringBuffer::Alloc(totalCustomLength);
// Subtract off the null terminator when reading. // Subtract off the null terminator when reading.
totalCustomLength--; totalCustomLength--;

View file

@ -652,7 +652,7 @@ void FetchUtil::InitWasmAltDataType() {
MOZ_ASSERT(type.IsEmpty()); MOZ_ASSERT(type.IsEmpty());
RunOnShutdown([]() { RunOnShutdown([]() {
// Avoid nsStringBuffer leak tests failures. // Avoid StringBuffer leak tests failures.
const_cast<nsCString&>(WasmAltDataType).Truncate(); const_cast<nsCString&>(WasmAltDataType).Truncate();
}); });

View file

@ -36,7 +36,7 @@
#include "nsTArray.h" #include "nsTArray.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsStringBuffer.h" #include "mozilla/StringBuffer.h"
#include "mozilla/dom/Comment.h" #include "mozilla/dom/Comment.h"
#include "mozilla/dom/Document.h" #include "mozilla/dom/Document.h"
#include "mozilla/dom/DocumentType.h" #include "mozilla/dom/DocumentType.h"
@ -341,7 +341,7 @@ class nsDocumentEncoder : public nsIDocumentEncoder {
// argument of nsIContentSerializer::Init(). // argument of nsIContentSerializer::Init().
bool mNeedsPreformatScanning; bool mNeedsPreformatScanning;
bool mIsCopying; // Set to true only while copying bool mIsCopying; // Set to true only while copying
RefPtr<nsStringBuffer> mCachedBuffer; RefPtr<StringBuffer> mCachedBuffer;
class NodeSerializer { class NodeSerializer {
public: public:
@ -1368,7 +1368,7 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
nsString output; nsString output;
static const size_t kStringBufferSizeInBytes = 2048; static const size_t kStringBufferSizeInBytes = 2048;
if (!mCachedBuffer) { if (!mCachedBuffer) {
mCachedBuffer = nsStringBuffer::Alloc(kStringBufferSizeInBytes); mCachedBuffer = StringBuffer::Alloc(kStringBufferSizeInBytes);
if (NS_WARN_IF(!mCachedBuffer)) { if (NS_WARN_IF(!mCachedBuffer)) {
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -1406,7 +1406,7 @@ nsDocumentEncoder::EncodeToStringWithMaxLength(uint32_t aMaxLength,
bool setOutput = false; bool setOutput = false;
MOZ_ASSERT(!mCachedBuffer); MOZ_ASSERT(!mCachedBuffer);
// Try to cache the buffer. // Try to cache the buffer.
if (nsStringBuffer* outputBuffer = output.GetStringBuffer()) { if (StringBuffer* outputBuffer = output.GetStringBuffer()) {
if (outputBuffer->StorageSize() == kStringBufferSizeInBytes && if (outputBuffer->StorageSize() == kStringBufferSizeInBytes &&
!outputBuffer->IsReadonly()) { !outputBuffer->IsReadonly()) {
mCachedBuffer = outputBuffer; mCachedBuffer = outputBuffer;

View file

@ -83,7 +83,6 @@
#include "nsIWindowWatcher.h" #include "nsIWindowWatcher.h"
#include "nsIConsoleService.h" #include "nsIConsoleService.h"
#include "nsAsyncRedirectVerifyHelper.h" #include "nsAsyncRedirectVerifyHelper.h"
#include "nsStringBuffer.h"
#include "nsIFileChannel.h" #include "nsIFileChannel.h"
#include "mozilla/Telemetry.h" #include "mozilla/Telemetry.h"
#include "js/ArrayBuffer.h" // JS::{Create,Release}MappedArrayBufferContents,New{,Mapped}ArrayBufferWithContents #include "js/ArrayBuffer.h" // JS::{Create,Release}MappedArrayBufferContents,New{,Mapped}ArrayBufferWithContents

View file

@ -58,7 +58,7 @@ class XMLHttpRequestStringBuffer final {
// XXX: Bug 1408793 suggests encapsulating the following sequence within // XXX: Bug 1408793 suggests encapsulating the following sequence within
// DOMString. // DOMString.
if (nsStringBuffer* buf = mData.GetStringBuffer()) { if (StringBuffer* buf = mData.GetStringBuffer()) {
// We have to use SetStringBuffer, because once we release our mutex mData // We have to use SetStringBuffer, because once we release our mutex mData
// can get mutated from some other thread while the DOMString is still // can get mutated from some other thread while the DOMString is still
// alive. // alive.

View file

@ -286,10 +286,6 @@ function checkFieldWrite(entry, location, fields)
if (/\bThreadLocal<\b/.test(field)) if (/\bThreadLocal<\b/.test(field))
return; return;
// Debugging check for string corruption.
if (field == "nsStringBuffer.mCanary")
return;
} }
var str = ""; var str = "";
@ -539,7 +535,7 @@ function ignoreContents(entry)
if (entry.isSafeArgument(2)) { if (entry.isSafeArgument(2)) {
var secondArgWhitelist = [ var secondArgWhitelist = [
/nsStringBuffer::ToString/, /StringBuffer::ToString/,
/AppendUTF\d+toUTF\d+/, /AppendUTF\d+toUTF\d+/,
/AppendASCIItoUTF\d+/, /AppendASCIItoUTF\d+/,
]; ];

View file

@ -165,7 +165,7 @@ bool XPCConvert::NativeData2JS(JSContext* cx, MutableHandleValue d,
return true; return true;
} }
nsStringBuffer* buf; StringBuffer* buf;
if (!XPCStringConvert::ReadableToJSVal(cx, *p, &buf, d)) { if (!XPCStringConvert::ReadableToJSVal(cx, *p, &buf, d)) {
return false; return false;
} }
@ -255,7 +255,7 @@ bool XPCConvert::NativeData2JS(JSContext* cx, MutableHandleValue d,
// NOTE: XPCStringConvert::UTF8ToJSVal cannot be used here because // NOTE: XPCStringConvert::UTF8ToJSVal cannot be used here because
// it requires valid UTF-8 sequence. // it requires valid UTF-8 sequence.
if (mozilla::IsAscii(*utf8String)) { if (mozilla::IsAscii(*utf8String)) {
nsStringBuffer* buf; StringBuffer* buf;
if (!XPCStringConvert::Latin1ToJSVal(cx, *utf8String, &buf, d)) { if (!XPCStringConvert::Latin1ToJSVal(cx, *utf8String, &buf, d)) {
return false; return false;
} }
@ -312,7 +312,7 @@ bool XPCConvert::NativeData2JS(JSContext* cx, MutableHandleValue d,
} }
// c-strings (binary blobs) are Latin1 string in JSAPI. // c-strings (binary blobs) are Latin1 string in JSAPI.
nsStringBuffer* buf; StringBuffer* buf;
if (!XPCStringConvert::Latin1ToJSVal(cx, *cString, &buf, d)) { if (!XPCStringConvert::Latin1ToJSVal(cx, *cString, &buf, d)) {
return false; return false;
} }

View file

@ -20,11 +20,12 @@
#include "nscore.h" #include "nscore.h"
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h" #include "mozilla/StringBuffer.h"
#include "jsapi.h" #include "jsapi.h"
#include "xpcpublic.h" #include "xpcpublic.h"
using namespace JS; using namespace JS;
using mozilla::StringBuffer;
const XPCStringConvert::LiteralExternalString const XPCStringConvert::LiteralExternalString
XPCStringConvert::sLiteralExternalString; XPCStringConvert::sLiteralExternalString;
@ -55,13 +56,13 @@ size_t XPCStringConvert::LiteralExternalString::sizeOfBuffer(
void XPCStringConvert::DOMStringExternalString::finalize( void XPCStringConvert::DOMStringExternalString::finalize(
JS::Latin1Char* aChars) const { JS::Latin1Char* aChars) const {
nsStringBuffer* buf = nsStringBuffer::FromData(aChars); StringBuffer* buf = StringBuffer::FromData(aChars);
buf->Release(); buf->Release();
} }
void XPCStringConvert::DOMStringExternalString::finalize( void XPCStringConvert::DOMStringExternalString::finalize(
char16_t* aChars) const { char16_t* aChars) const {
nsStringBuffer* buf = nsStringBuffer::FromData(aChars); StringBuffer* buf = StringBuffer::FromData(aChars);
buf->Release(); buf->Release();
} }
@ -70,8 +71,8 @@ size_t XPCStringConvert::DOMStringExternalString::sizeOfBuffer(
// We promised the JS engine we would not GC. Enforce that: // We promised the JS engine we would not GC. Enforce that:
JS::AutoCheckCannotGC autoCannotGC; JS::AutoCheckCannotGC autoCannotGC;
const nsStringBuffer* buf = const StringBuffer* buf =
nsStringBuffer::FromData(const_cast<JS::Latin1Char*>(aChars)); StringBuffer::FromData(const_cast<JS::Latin1Char*>(aChars));
// We want sizeof including this, because the entire string buffer is owned by // We want sizeof including this, because the entire string buffer is owned by
// the external string. But only report here if we're unshared; if we're // the external string. But only report here if we're unshared; if we're
// shared then we don't know who really owns this data. // shared then we don't know who really owns this data.
@ -83,8 +84,8 @@ size_t XPCStringConvert::DOMStringExternalString::sizeOfBuffer(
// We promised the JS engine we would not GC. Enforce that: // We promised the JS engine we would not GC. Enforce that:
JS::AutoCheckCannotGC autoCannotGC; JS::AutoCheckCannotGC autoCannotGC;
const nsStringBuffer* buf = const StringBuffer* buf =
nsStringBuffer::FromData(const_cast<char16_t*>(aChars)); StringBuffer::FromData(const_cast<char16_t*>(aChars));
// We want sizeof including this, because the entire string buffer is owned by // We want sizeof including this, because the entire string buffer is owned by
// the external string. But only report here if we're unshared; if we're // the external string. But only report here if we're unshared; if we're
// shared then we don't know who really owns this data. // shared then we don't know who really owns this data.
@ -94,7 +95,7 @@ size_t XPCStringConvert::DOMStringExternalString::sizeOfBuffer(
// convert a readable to a JSString, copying string data // convert a readable to a JSString, copying string data
// static // static
bool XPCStringConvert::ReadableToJSVal(JSContext* cx, const nsAString& readable, bool XPCStringConvert::ReadableToJSVal(JSContext* cx, const nsAString& readable,
nsStringBuffer** sharedBuffer, StringBuffer** sharedBuffer,
MutableHandleValue vp) { MutableHandleValue vp) {
*sharedBuffer = nullptr; *sharedBuffer = nullptr;
@ -104,7 +105,7 @@ bool XPCStringConvert::ReadableToJSVal(JSContext* cx, const nsAString& readable,
return StringLiteralToJSVal(cx, readable.BeginReading(), length, vp); return StringLiteralToJSVal(cx, readable.BeginReading(), length, vp);
} }
if (nsStringBuffer* buf = readable.GetStringBuffer()) { if (StringBuffer* buf = readable.GetStringBuffer()) {
bool shared; bool shared;
if (!UCStringBufferToJSVal(cx, buf, length, vp, &shared)) { if (!UCStringBufferToJSVal(cx, buf, length, vp, &shared)) {
return false; return false;
@ -125,7 +126,7 @@ bool XPCStringConvert::ReadableToJSVal(JSContext* cx, const nsAString& readable,
} }
bool XPCStringConvert::Latin1ToJSVal(JSContext* cx, const nsACString& latin1, bool XPCStringConvert::Latin1ToJSVal(JSContext* cx, const nsACString& latin1,
nsStringBuffer** sharedBuffer, StringBuffer** sharedBuffer,
MutableHandleValue vp) { MutableHandleValue vp) {
*sharedBuffer = nullptr; *sharedBuffer = nullptr;
@ -137,7 +138,7 @@ bool XPCStringConvert::Latin1ToJSVal(JSContext* cx, const nsACString& latin1,
length, vp); length, vp);
} }
if (nsStringBuffer* buf = latin1.GetStringBuffer()) { if (StringBuffer* buf = latin1.GetStringBuffer()) {
bool shared; bool shared;
if (!Latin1StringBufferToJSVal(cx, buf, length, vp, &shared)) { if (!Latin1StringBufferToJSVal(cx, buf, length, vp, &shared)) {
return false; return false;
@ -157,7 +158,7 @@ bool XPCStringConvert::Latin1ToJSVal(JSContext* cx, const nsACString& latin1,
} }
bool XPCStringConvert::UTF8ToJSVal(JSContext* cx, const nsACString& utf8, bool XPCStringConvert::UTF8ToJSVal(JSContext* cx, const nsACString& utf8,
nsStringBuffer** sharedBuffer, StringBuffer** sharedBuffer,
MutableHandleValue vp) { MutableHandleValue vp) {
*sharedBuffer = nullptr; *sharedBuffer = nullptr;
@ -168,7 +169,7 @@ bool XPCStringConvert::UTF8ToJSVal(JSContext* cx, const nsACString& utf8,
cx, JS::UTF8Chars(utf8.BeginReading(), length), vp); cx, JS::UTF8Chars(utf8.BeginReading(), length), vp);
} }
if (nsStringBuffer* buf = utf8.GetStringBuffer()) { if (StringBuffer* buf = utf8.GetStringBuffer()) {
bool shared; bool shared;
if (!UTF8StringBufferToJSVal(cx, buf, length, vp, &shared)) { if (!UTF8StringBufferToJSVal(cx, buf, length, vp, &shared)) {
return false; return false;
@ -192,7 +193,7 @@ namespace xpc {
bool NonVoidStringToJsval(JSContext* cx, nsAString& str, bool NonVoidStringToJsval(JSContext* cx, nsAString& str,
MutableHandleValue rval) { MutableHandleValue rval) {
nsStringBuffer* sharedBuffer; StringBuffer* sharedBuffer;
if (!XPCStringConvert::ReadableToJSVal(cx, str, &sharedBuffer, rval)) { if (!XPCStringConvert::ReadableToJSVal(cx, str, &sharedBuffer, rval)) {
return false; return false;
} }
@ -207,7 +208,7 @@ bool NonVoidStringToJsval(JSContext* cx, nsAString& str,
bool NonVoidStringToJsval(JSContext* cx, const nsAString& str, bool NonVoidStringToJsval(JSContext* cx, const nsAString& str,
MutableHandleValue rval) { MutableHandleValue rval) {
nsStringBuffer* sharedBuffer; StringBuffer* sharedBuffer;
if (!XPCStringConvert::ReadableToJSVal(cx, str, &sharedBuffer, rval)) { if (!XPCStringConvert::ReadableToJSVal(cx, str, &sharedBuffer, rval)) {
return false; return false;
} }
@ -221,7 +222,7 @@ bool NonVoidStringToJsval(JSContext* cx, const nsAString& str,
bool NonVoidLatin1StringToJsval(JSContext* cx, nsACString& str, bool NonVoidLatin1StringToJsval(JSContext* cx, nsACString& str,
MutableHandleValue rval) { MutableHandleValue rval) {
nsStringBuffer* sharedBuffer; StringBuffer* sharedBuffer;
if (!XPCStringConvert::Latin1ToJSVal(cx, str, &sharedBuffer, rval)) { if (!XPCStringConvert::Latin1ToJSVal(cx, str, &sharedBuffer, rval)) {
return false; return false;
} }
@ -236,7 +237,7 @@ bool NonVoidLatin1StringToJsval(JSContext* cx, nsACString& str,
bool NonVoidLatin1StringToJsval(JSContext* cx, const nsACString& str, bool NonVoidLatin1StringToJsval(JSContext* cx, const nsACString& str,
MutableHandleValue rval) { MutableHandleValue rval) {
nsStringBuffer* sharedBuffer; StringBuffer* sharedBuffer;
if (!XPCStringConvert::Latin1ToJSVal(cx, str, &sharedBuffer, rval)) { if (!XPCStringConvert::Latin1ToJSVal(cx, str, &sharedBuffer, rval)) {
return false; return false;
} }
@ -250,7 +251,7 @@ bool NonVoidLatin1StringToJsval(JSContext* cx, const nsACString& str,
bool NonVoidUTF8StringToJsval(JSContext* cx, nsACString& str, bool NonVoidUTF8StringToJsval(JSContext* cx, nsACString& str,
MutableHandleValue rval) { MutableHandleValue rval) {
nsStringBuffer* sharedBuffer; StringBuffer* sharedBuffer;
if (!XPCStringConvert::UTF8ToJSVal(cx, str, &sharedBuffer, rval)) { if (!XPCStringConvert::UTF8ToJSVal(cx, str, &sharedBuffer, rval)) {
return false; return false;
} }
@ -265,7 +266,7 @@ bool NonVoidUTF8StringToJsval(JSContext* cx, nsACString& str,
bool NonVoidUTF8StringToJsval(JSContext* cx, const nsACString& str, bool NonVoidUTF8StringToJsval(JSContext* cx, const nsACString& str,
MutableHandleValue rval) { MutableHandleValue rval) {
nsStringBuffer* sharedBuffer; StringBuffer* sharedBuffer;
if (!XPCStringConvert::UTF8ToJSVal(cx, str, &sharedBuffer, rval)) { if (!XPCStringConvert::UTF8ToJSVal(cx, str, &sharedBuffer, rval)) {
return false; return false;
} }

View file

@ -138,7 +138,6 @@
#include "nsBaseHashtable.h" #include "nsBaseHashtable.h"
#include "nsHashKeys.h" #include "nsHashKeys.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
#include "nsStringBuffer.h"
#include "nsDeque.h" #include "nsDeque.h"
#include "nsIScriptSecurityManager.h" #include "nsIScriptSecurityManager.h"

View file

@ -28,12 +28,12 @@
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "mozilla/TextUtils.h" #include "mozilla/TextUtils.h"
#include "mozilla/dom/DOMString.h" #include "mozilla/dom/DOMString.h"
#include "mozilla/StringBuffer.h"
#include "mozilla/fallible.h" #include "mozilla/fallible.h"
#include "nsAtom.h" #include "nsAtom.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsISupports.h" #include "nsISupports.h"
#include "nsIURI.h" #include "nsIURI.h"
#include "nsStringBuffer.h"
#include "nsStringFwd.h" #include "nsStringFwd.h"
#include "nsTArray.h" #include "nsTArray.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
@ -236,11 +236,11 @@ extern bool xpc_DumpJSStack(bool showArgs, bool showLocals, bool showThisProps);
extern JS::UniqueChars xpc_PrintJSStack(JSContext* cx, bool showArgs, extern JS::UniqueChars xpc_PrintJSStack(JSContext* cx, bool showArgs,
bool showLocals, bool showThisProps); bool showLocals, bool showThisProps);
inline void AssignFromStringBuffer(nsStringBuffer* buffer, size_t len, inline void AssignFromStringBuffer(mozilla::StringBuffer* buffer, size_t len,
nsAString& dest) { nsAString& dest) {
dest.Assign(buffer, len); dest.Assign(buffer, len);
} }
inline void AssignFromStringBuffer(nsStringBuffer* buffer, size_t len, inline void AssignFromStringBuffer(mozilla::StringBuffer* buffer, size_t len,
nsACString& dest) { nsACString& dest) {
dest.Assign(buffer, len); dest.Assign(buffer, len);
} }
@ -252,18 +252,18 @@ class XPCStringConvert {
// get assigned to *sharedBuffer. Otherwise null will be // get assigned to *sharedBuffer. Otherwise null will be
// assigned. // assigned.
static bool ReadableToJSVal(JSContext* cx, const nsAString& readable, static bool ReadableToJSVal(JSContext* cx, const nsAString& readable,
nsStringBuffer** sharedBuffer, mozilla::StringBuffer** sharedBuffer,
JS::MutableHandle<JS::Value> vp); JS::MutableHandle<JS::Value> vp);
static bool Latin1ToJSVal(JSContext* cx, const nsACString& latin1, static bool Latin1ToJSVal(JSContext* cx, const nsACString& latin1,
nsStringBuffer** sharedBuffer, mozilla::StringBuffer** sharedBuffer,
JS::MutableHandle<JS::Value> vp); JS::MutableHandle<JS::Value> vp);
static bool UTF8ToJSVal(JSContext* cx, const nsACString& utf8, static bool UTF8ToJSVal(JSContext* cx, const nsACString& utf8,
nsStringBuffer** sharedBuffer, mozilla::StringBuffer** sharedBuffer,
JS::MutableHandle<JS::Value> vp); JS::MutableHandle<JS::Value> vp);
// Convert the given stringbuffer/length pair to a jsval // Convert the given stringbuffer/length pair to a jsval
static MOZ_ALWAYS_INLINE bool UCStringBufferToJSVal( static MOZ_ALWAYS_INLINE bool UCStringBufferToJSVal(
JSContext* cx, nsStringBuffer* buf, uint32_t length, JSContext* cx, mozilla::StringBuffer* buf, uint32_t length,
JS::MutableHandle<JS::Value> rval, bool* sharedBuffer) { JS::MutableHandle<JS::Value> rval, bool* sharedBuffer) {
JSString* str = JS_NewMaybeExternalUCString( JSString* str = JS_NewMaybeExternalUCString(
cx, static_cast<const char16_t*>(buf->Data()), length, cx, static_cast<const char16_t*>(buf->Data()), length,
@ -276,7 +276,7 @@ class XPCStringConvert {
} }
static MOZ_ALWAYS_INLINE bool Latin1StringBufferToJSVal( static MOZ_ALWAYS_INLINE bool Latin1StringBufferToJSVal(
JSContext* cx, nsStringBuffer* buf, uint32_t length, JSContext* cx, mozilla::StringBuffer* buf, uint32_t length,
JS::MutableHandle<JS::Value> rval, bool* sharedBuffer) { JS::MutableHandle<JS::Value> rval, bool* sharedBuffer) {
JSString* str = JS_NewMaybeExternalStringLatin1( JSString* str = JS_NewMaybeExternalStringLatin1(
cx, static_cast<const JS::Latin1Char*>(buf->Data()), length, cx, static_cast<const JS::Latin1Char*>(buf->Data()), length,
@ -289,7 +289,7 @@ class XPCStringConvert {
} }
static MOZ_ALWAYS_INLINE bool UTF8StringBufferToJSVal( static MOZ_ALWAYS_INLINE bool UTF8StringBufferToJSVal(
JSContext* cx, nsStringBuffer* buf, uint32_t length, JSContext* cx, mozilla::StringBuffer* buf, uint32_t length,
JS::MutableHandle<JS::Value> rval, bool* sharedBuffer) { JS::MutableHandle<JS::Value> rval, bool* sharedBuffer) {
JSString* str = JS_NewMaybeExternalStringUTF8( JSString* str = JS_NewMaybeExternalStringUTF8(
cx, {static_cast<const char*>(buf->Data()), length}, cx, {static_cast<const char*>(buf->Data()), length},
@ -387,9 +387,10 @@ class XPCStringConvert {
// the whole buffer; otherwise we have to copy. // the whole buffer; otherwise we have to copy.
if (chars[len] == '\0') { if (chars[len] == '\0') {
// NOTE: No need to worry about SrcCharT vs DestCharT, given // NOTE: No need to worry about SrcCharT vs DestCharT, given
// nsStringBuffer::FromData takes void*. // mozilla::StringBuffer::FromData takes void*.
AssignFromStringBuffer( AssignFromStringBuffer(
nsStringBuffer::FromData(const_cast<DestCharT*>(chars)), len, dest); mozilla::StringBuffer::FromData(const_cast<DestCharT*>(chars)), len,
dest);
return true; return true;
} }
} else if (callbacks == &sLiteralExternalString) { } else if (callbacks == &sLiteralExternalString) {
@ -504,7 +505,7 @@ inline bool NonVoidStringToJsval(JSContext* cx, mozilla::dom::DOMString& str,
if (str.HasStringBuffer()) { if (str.HasStringBuffer()) {
uint32_t length = str.StringBufferLength(); uint32_t length = str.StringBufferLength();
nsStringBuffer* buf = str.StringBuffer(); mozilla::StringBuffer* buf = str.StringBuffer();
bool shared; bool shared;
if (!XPCStringConvert::UCStringBufferToJSVal(cx, buf, length, rval, if (!XPCStringConvert::UCStringBufferToJSVal(cx, buf, length, rval,
&shared)) { &shared)) {

View file

@ -17,7 +17,6 @@
#include "mozilla/DbgMacro.h" #include "mozilla/DbgMacro.h"
#include "mozilla/AnimatedPropertyID.h" #include "mozilla/AnimatedPropertyID.h"
#include "nsStringFwd.h" #include "nsStringFwd.h"
#include "nsStringBuffer.h"
#include "nsCoord.h" #include "nsCoord.h"
#include "nsColor.h" #include "nsColor.h"
#include "nsCSSPropertyID.h" #include "nsCSSPropertyID.h"

View file

@ -4,15 +4,18 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsStringBuffer_h__ #ifndef StringBuffer_h__
#define nsStringBuffer_h__ #define StringBuffer_h__
#include <atomic> #include <atomic>
#include <cstring>
#include "mozilla/MemoryReporting.h" #include "mozilla/MemoryReporting.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/AlreadyAddRefed.h" #include "mozilla/AlreadyAddRefed.h"
#include "mozilla/RefCounted.h" #include "mozilla/RefCounted.h"
namespace mozilla {
/** /**
* This structure precedes the string buffers "we" allocate. It may be the * This structure precedes the string buffers "we" allocate. It may be the
* case that nsTAString::mData does not point to one of these special * case that nsTAString::mData does not point to one of these special
@ -22,13 +25,13 @@
* tracking. NOTE: A string buffer can be modified only if its reference * tracking. NOTE: A string buffer can be modified only if its reference
* count is 1. * count is 1.
*/ */
class nsStringBuffer { class StringBuffer {
private: private:
std::atomic<uint32_t> mRefCount; std::atomic<uint32_t> mRefCount;
uint32_t mStorageSize; uint32_t mStorageSize;
public: public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(nsStringBuffer) MOZ_DECLARE_REFCOUNTED_TYPENAME(StringBuffer)
/** /**
* Allocates a new string buffer, with given size in bytes and a * Allocates a new string buffer, with given size in bytes and a
@ -47,17 +50,17 @@ class nsStringBuffer {
* *
* @return new string buffer or null if out of memory. * @return new string buffer or null if out of memory.
*/ */
static already_AddRefed<nsStringBuffer> Alloc(size_t aSize) { static already_AddRefed<StringBuffer> Alloc(size_t aSize) {
MOZ_ASSERT(aSize != 0, "zero capacity allocation not allowed"); MOZ_ASSERT(aSize != 0, "zero capacity allocation not allowed");
MOZ_ASSERT(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) && MOZ_ASSERT(sizeof(StringBuffer) + aSize <= size_t(uint32_t(-1)) &&
sizeof(nsStringBuffer) + aSize > aSize, sizeof(StringBuffer) + aSize > aSize,
"mStorageSize will truncate"); "mStorageSize will truncate");
auto* hdr = (nsStringBuffer*)malloc(sizeof(nsStringBuffer) + aSize); auto* hdr = (StringBuffer*)malloc(sizeof(StringBuffer) + aSize);
if (hdr) { if (hdr) {
hdr->mRefCount = 1; hdr->mRefCount = 1;
hdr->mStorageSize = aSize; hdr->mStorageSize = aSize;
mozilla::detail::RefCountLogger::logAddRef(hdr, 1); detail::RefCountLogger::logAddRef(hdr, 1);
} }
return already_AddRefed(hdr); return already_AddRefed(hdr);
} }
@ -68,10 +71,14 @@ class nsStringBuffer {
* Note that this will allocate extra space for the trailing null byte, which * Note that this will allocate extra space for the trailing null byte, which
* this method will add. * this method will add.
*/ */
static already_AddRefed<nsStringBuffer> Create(const char16_t* aData, static already_AddRefed<StringBuffer> Create(const char16_t* aData,
size_t aLength); size_t aLength) {
static already_AddRefed<nsStringBuffer> Create(const char* aData, return DoCreate(aData, aLength);
size_t aLength); }
static already_AddRefed<StringBuffer> Create(const char* aData,
size_t aLength) {
return DoCreate(aData, aLength);
}
/** /**
* Resizes the given string buffer to the specified storage size. This * Resizes the given string buffer to the specified storage size. This
@ -84,7 +91,31 @@ class nsStringBuffer {
* *
* @see IsReadonly * @see IsReadonly
*/ */
static nsStringBuffer* Realloc(nsStringBuffer* aBuf, size_t aStorageSize); static StringBuffer* Realloc(StringBuffer* aHdr, size_t aSize) {
MOZ_ASSERT(aSize != 0, "zero capacity allocation not allowed");
MOZ_ASSERT(sizeof(StringBuffer) + aSize <= size_t(uint32_t(-1)) &&
sizeof(StringBuffer) + aSize > aSize,
"mStorageSize will truncate");
// no point in trying to save ourselves if we hit this assertion
MOZ_ASSERT(!aHdr->IsReadonly(), "|Realloc| attempted on readonly string");
// Treat this as a release and addref for refcounting purposes, since we
// just asserted that the refcount is 1. If we don't do that, refcount
// logging will claim we've leaked all sorts of stuff.
{
detail::RefCountLogger::ReleaseLogger logger(aHdr);
logger.logRelease(0);
}
aHdr = (StringBuffer*)realloc(aHdr, sizeof(StringBuffer) + aSize);
if (aHdr) {
detail::RefCountLogger::logAddRef(aHdr, 1);
aHdr->mStorageSize = aSize;
}
return aHdr;
}
void AddRef() { void AddRef() {
// Memory synchronization is not required when incrementing a // Memory synchronization is not required when incrementing a
@ -96,14 +127,14 @@ class nsStringBuffer {
// synchronization is done by the mechanism that transfers the // synchronization is done by the mechanism that transfers the
// pointer between threads. // pointer between threads.
uint32_t count = mRefCount.fetch_add(1, std::memory_order_relaxed) + 1; uint32_t count = mRefCount.fetch_add(1, std::memory_order_relaxed) + 1;
mozilla::detail::RefCountLogger::logAddRef(this, count); detail::RefCountLogger::logAddRef(this, count);
} }
void Release() { void Release() {
// Since this may be the last release on this thread, we need release // Since this may be the last release on this thread, we need release
// semantics so that prior writes on this thread are visible to the thread // semantics so that prior writes on this thread are visible to the thread
// that destroys the object when it reads mValue with acquire semantics. // that destroys the object when it reads mValue with acquire semantics.
mozilla::detail::RefCountLogger::ReleaseLogger logger(this); detail::RefCountLogger::ReleaseLogger logger(this);
uint32_t count = mRefCount.fetch_sub(1, std::memory_order_release) - 1; uint32_t count = mRefCount.fetch_sub(1, std::memory_order_release) - 1;
logger.logRelease(count); logger.logRelease(count);
if (count == 0) { if (count == 0) {
@ -119,10 +150,10 @@ class nsStringBuffer {
/** /**
* This method returns the string buffer corresponding to the given data * This method returns the string buffer corresponding to the given data
* pointer. The data pointer must have been returned previously by a * pointer. The data pointer must have been returned previously by a
* call to the nsStringBuffer::Data method. * call to the StringBuffer::Data method.
*/ */
static nsStringBuffer* FromData(void* aData) { static StringBuffer* FromData(void* aData) {
return reinterpret_cast<nsStringBuffer*>(aData) - 1; return reinterpret_cast<StringBuffer*>(aData) - 1;
} }
/** /**
@ -182,8 +213,9 @@ class nsStringBuffer {
/** /**
* This measures the size only if the StringBuffer is unshared. * This measures the size only if the StringBuffer is unshared.
*/ */
size_t SizeOfIncludingThisIfUnshared( size_t SizeOfIncludingThisIfUnshared(MallocSizeOf aMallocSizeOf) const {
mozilla::MallocSizeOf aMallocSizeOf) const; return IsReadonly() ? 0 : aMallocSizeOf(this);
}
/** /**
* This measures the size regardless of whether the StringBuffer is * This measures the size regardless of whether the StringBuffer is
@ -194,8 +226,24 @@ class nsStringBuffer {
* please explain clearly in a comment why it's safe and won't lead to * please explain clearly in a comment why it's safe and won't lead to
* double-counting. * double-counting.
*/ */
size_t SizeOfIncludingThisEvenIfShared( size_t SizeOfIncludingThisEvenIfShared(MallocSizeOf aMallocSizeOf) const {
mozilla::MallocSizeOf aMallocSizeOf) const; return aMallocSizeOf(this);
}
private:
template <typename CharT>
static already_AddRefed<StringBuffer> DoCreate(const CharT* aData,
size_t aLength) {
StringBuffer* buffer = Alloc((aLength + 1) * sizeof(CharT)).take();
if (MOZ_LIKELY(buffer)) {
auto* data = reinterpret_cast<CharT*>(buffer->Data());
memcpy(data, aData, aLength * sizeof(CharT));
data[aLength] = 0;
}
return already_AddRefed(buffer);
}
}; };
#endif /* !defined(nsStringBuffer_h__ */ } // namespace mozilla
#endif

View file

@ -107,6 +107,7 @@ EXPORTS.mozilla = [
"SplayTree.h", "SplayTree.h",
"SPSCQueue.h", "SPSCQueue.h",
"StaticAnalysisFunctions.h", "StaticAnalysisFunctions.h",
"StringBuffer.h",
"TaggedAnonymousMemory.h", "TaggedAnonymousMemory.h",
"Tainting.h", "Tainting.h",
"TemplateLib.h", "TemplateLib.h",

View file

@ -5,6 +5,9 @@
#include "nsHtml5String.h" #include "nsHtml5String.h"
#include "nsCharTraits.h" #include "nsCharTraits.h"
#include "nsHtml5TreeBuilder.h" #include "nsHtml5TreeBuilder.h"
#include "mozilla/StringBuffer.h"
using mozilla::StringBuffer;
void nsHtml5String::ToString(nsAString& aString) { void nsHtml5String::ToString(nsAString& aString) {
switch (GetKind()) { switch (GetKind()) {
@ -104,17 +107,17 @@ nsHtml5String nsHtml5String::FromBuffer(char16_t* aBuffer, int32_t aLength,
if (!aLength) { if (!aLength) {
return nsHtml5String(eEmpty); return nsHtml5String(eEmpty);
} }
// Work with nsStringBuffer directly to make sure that storage is actually // Work with StringBuffer directly to make sure that storage is actually
// nsStringBuffer and to make sure the allocation strategy matches // StringBuffer and to make sure the allocation strategy matches
// nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and
// copy. // copy.
RefPtr<nsStringBuffer> buffer = nsStringBuffer::Create(aBuffer, aLength); RefPtr<StringBuffer> buffer = StringBuffer::Create(aBuffer, aLength);
if (MOZ_UNLIKELY(!buffer)) { if (MOZ_UNLIKELY(!buffer)) {
if (!aTreeBuilder) { if (!aTreeBuilder) {
MOZ_CRASH("Out of memory."); MOZ_CRASH("Out of memory.");
} }
aTreeBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY); aTreeBuilder->MarkAsBroken(NS_ERROR_OUT_OF_MEMORY);
buffer = nsStringBuffer::Alloc(2 * sizeof(char16_t)); buffer = StringBuffer::Alloc(2 * sizeof(char16_t));
if (!buffer) { if (!buffer) {
MOZ_CRASH( MOZ_CRASH(
"Out of memory so badly that couldn't even allocate placeholder."); "Out of memory so badly that couldn't even allocate placeholder.");
@ -133,12 +136,12 @@ nsHtml5String nsHtml5String::FromLiteral(const char* aLiteral) {
if (!length) { if (!length) {
return nsHtml5String(eEmpty); return nsHtml5String(eEmpty);
} }
// Work with nsStringBuffer directly to make sure that storage is actually // Work with StringBuffer directly to make sure that storage is actually
// nsStringBuffer and to make sure the allocation strategy matches // StringBuffer and to make sure the allocation strategy matches
// nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and // nsAttrValue::GetStringBuffer, so that it doesn't need to reallocate and
// copy. // copy.
RefPtr<nsStringBuffer> buffer( RefPtr<StringBuffer> buffer(
nsStringBuffer::Alloc((length + 1) * sizeof(char16_t))); StringBuffer::Alloc((length + 1) * sizeof(char16_t)));
if (!buffer) { if (!buffer) {
MOZ_CRASH("Out of memory."); MOZ_CRASH("Out of memory.");
} }
@ -156,14 +159,14 @@ nsHtml5String nsHtml5String::FromString(const nsAString& aString) {
if (!length) { if (!length) {
return nsHtml5String(eEmpty); return nsHtml5String(eEmpty);
} }
if (nsStringBuffer* buffer = aString.GetStringBuffer()) { if (StringBuffer* buffer = aString.GetStringBuffer()) {
if (length == buffer->StorageSize() / sizeof(char16_t) - 1) { if (length == buffer->StorageSize() / sizeof(char16_t) - 1) {
buffer->AddRef(); buffer->AddRef();
return nsHtml5String(reinterpret_cast<uintptr_t>(buffer) | eStringBuffer); return nsHtml5String(reinterpret_cast<uintptr_t>(buffer) | eStringBuffer);
} }
} }
RefPtr<nsStringBuffer> buffer = RefPtr<StringBuffer> buffer =
nsStringBuffer::Alloc((length + 1) * sizeof(char16_t)); StringBuffer::Alloc((length + 1) * sizeof(char16_t));
if (!buffer) { if (!buffer) {
MOZ_CRASH("Out of memory."); MOZ_CRASH("Out of memory.");
} }

View file

@ -7,7 +7,10 @@
#include "nsAtom.h" #include "nsAtom.h"
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h"
namespace mozilla {
class StringBuffer;
}
class nsHtml5TreeBuilder; class nsHtml5TreeBuilder;
@ -15,11 +18,11 @@ class nsHtml5TreeBuilder;
* A pass-by-value type that can represent * A pass-by-value type that can represent
* * nullptr * * nullptr
* * empty string * * empty string
* * Non-empty string as exactly-sized (capacity is length) `nsStringBuffer*` * * Non-empty string as exactly-sized (capacity is length) `StringBuffer*`
* * Non-empty string as an nsAtom* * * Non-empty string as an nsAtom*
* *
* Holding or passing this type is as unsafe as holding or passing * Holding or passing this type is as unsafe as holding or passing
* `nsStringBuffer*`/`nsAtom*`. * `StringBuffer*`/`nsAtom*`.
*/ */
class nsHtml5String final { class nsHtml5String final {
private: private:
@ -36,9 +39,9 @@ class nsHtml5String final {
inline Kind GetKind() const { return (Kind)(mBits & kKindMask); } inline Kind GetKind() const { return (Kind)(mBits & kKindMask); }
inline nsStringBuffer* AsStringBuffer() const { inline mozilla::StringBuffer* AsStringBuffer() const {
MOZ_ASSERT(GetKind() == eStringBuffer); MOZ_ASSERT(GetKind() == eStringBuffer);
return reinterpret_cast<nsStringBuffer*>(mBits & kPtrMask); return reinterpret_cast<mozilla::StringBuffer*>(mBits & kPtrMask);
} }
inline nsAtom* AsAtom() const { inline nsAtom* AsAtom() const {

View file

@ -35,7 +35,6 @@
#include "nsNSSComponent.h" #include "nsNSSComponent.h"
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsStreamUtils.h" #include "nsStreamUtils.h"
#include "nsStringBuffer.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
using namespace mozilla; using namespace mozilla;

View file

@ -17,7 +17,6 @@
#include "nsNetUtil.h" #include "nsNetUtil.h"
#include "nsPromiseFlatString.h" #include "nsPromiseFlatString.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsStringBuffer.h"
#include "cert.h" #include "cert.h"
#include "nspr.h" #include "nspr.h"
#include "pk11pub.h" #include "pk11pub.h"

View file

@ -41,7 +41,6 @@
#include "nsDOMMutationObserver.h" #include "nsDOMMutationObserver.h"
#include "nsJSUtils.h" #include "nsJSUtils.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "nsStringBuffer.h"
#include "nsThread.h" #include "nsThread.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"

View file

@ -97,7 +97,6 @@
#include "nsDOMJSUtils.h" #include "nsDOMJSUtils.h"
#include "nsExceptionHandler.h" #include "nsExceptionHandler.h"
#include "nsJSUtils.h" #include "nsJSUtils.h"
#include "nsStringBuffer.h"
#include "nsWrapperCache.h" #include "nsWrapperCache.h"
#include "prenv.h" #include "prenv.h"

View file

@ -353,14 +353,15 @@ static void DumpSerialNumbers(const SerialHash::ConstIterator& aHashEntry,
#endif #endif
if (aDumpAsStringBuffer) { if (aDumpAsStringBuffer) {
// This output will be wrong if the nsStringBuffer was used to // This output will be wrong if the StringBuffer was used to
// store a char16_t string. // store a char16_t string.
auto* buffer = static_cast<const nsStringBuffer*>(aHashEntry.Key()); auto* buffer = static_cast<const mozilla::StringBuffer*>(aHashEntry.Key());
nsDependentCString bufferString(static_cast<char*>(buffer->Data())); nsDependentCString bufferString(static_cast<char*>(buffer->Data()));
fprintf(outputFile, fprintf(
"Contents of leaked nsStringBuffer with storage size %d as a " outputFile,
"char*: %s\n", "Contents of leaked mozilla::StringBuffer with storage size %d as a "
buffer->StorageSize(), bufferString.get()); "char*: %s\n",
buffer->StorageSize(), bufferString.get());
} }
if (!record->allocationStack.empty()) { if (!record->allocationStack.empty()) {
@ -449,7 +450,7 @@ nsresult nsTraceRefcnt::DumpStatistics() {
if (gSerialNumbers) { if (gSerialNumbers) {
bool onlyLoggingStringBuffers = gTypesToLog && gTypesToLog->Count() == 1 && bool onlyLoggingStringBuffers = gTypesToLog && gTypesToLog->Count() == 1 &&
gTypesToLog->Contains("nsStringBuffer"); gTypesToLog->Contains("StringBuffer");
fprintf(gBloatLog, "\nSerial Numbers of Leaked Objects:\n"); fprintf(gBloatLog, "\nSerial Numbers of Leaked Objects:\n");
for (auto iter = gSerialNumbers->ConstIter(); !iter.Done(); iter.Next()) { for (auto iter = gSerialNumbers->ConstIter(); !iter.Done(); iter.Next()) {

View file

@ -177,7 +177,7 @@ class nsDynamicAtom : public nsAtom {
return count; return count;
} }
nsStringBuffer* StringBuffer() const { return mStringBuffer; } mozilla::StringBuffer* StringBuffer() const { return mStringBuffer; }
const char16_t* String() const { const char16_t* String() const {
return reinterpret_cast<const char16_t*>(mStringBuffer->Data()); return reinterpret_cast<const char16_t*>(mStringBuffer->Data());
@ -193,7 +193,7 @@ class nsDynamicAtom : public nsAtom {
// These shouldn't be used directly, even by friend classes. The // These shouldn't be used directly, even by friend classes. The
// Create()/Destroy() methods use them. // Create()/Destroy() methods use them.
nsDynamicAtom(already_AddRefed<nsStringBuffer>, uint32_t aLength, nsDynamicAtom(already_AddRefed<mozilla::StringBuffer>, uint32_t aLength,
uint32_t aHash, bool aIsAsciiLowercase); uint32_t aHash, bool aIsAsciiLowercase);
~nsDynamicAtom() = default; ~nsDynamicAtom() = default;
@ -201,7 +201,7 @@ class nsDynamicAtom : public nsAtom {
static void Destroy(nsDynamicAtom* aAtom); static void Destroy(nsDynamicAtom* aAtom);
mozilla::ThreadSafeAutoRefCnt mRefCnt; mozilla::ThreadSafeAutoRefCnt mRefCnt;
RefPtr<nsStringBuffer> mStringBuffer; RefPtr<mozilla::StringBuffer> mStringBuffer;
}; };
const nsStaticAtom* nsAtom::AsStatic() const { const nsStaticAtom* nsAtom::AsStatic() const {

View file

@ -61,7 +61,7 @@ enum class GCKind {
// replaying. // replaying.
Atomic<int32_t, ReleaseAcquire> nsDynamicAtom::gUnusedAtomCount; Atomic<int32_t, ReleaseAcquire> nsDynamicAtom::gUnusedAtomCount;
nsDynamicAtom::nsDynamicAtom(already_AddRefed<nsStringBuffer> aBuffer, nsDynamicAtom::nsDynamicAtom(already_AddRefed<mozilla::StringBuffer> aBuffer,
uint32_t aLength, uint32_t aHash, uint32_t aLength, uint32_t aHash,
bool aIsAsciiLowercase) bool aIsAsciiLowercase)
: nsAtom(aLength, /* aIsStatic = */ false, aHash, aIsAsciiLowercase), : nsAtom(aLength, /* aIsStatic = */ false, aHash, aIsAsciiLowercase),
@ -82,9 +82,9 @@ nsDynamicAtom* nsDynamicAtom::Create(const nsAString& aString, uint32_t aHash) {
// We tack the chars onto the end of the nsDynamicAtom object. // We tack the chars onto the end of the nsDynamicAtom object.
const bool isAsciiLower = const bool isAsciiLower =
::IsAsciiLowercase(aString.Data(), aString.Length()); ::IsAsciiLowercase(aString.Data(), aString.Length());
RefPtr<nsStringBuffer> buffer = aString.GetStringBuffer(); RefPtr<mozilla::StringBuffer> buffer = aString.GetStringBuffer();
if (!buffer) { if (!buffer) {
buffer = nsStringBuffer::Create(aString.Data(), aString.Length()); buffer = mozilla::StringBuffer::Create(aString.Data(), aString.Length());
if (MOZ_UNLIKELY(!buffer)) { if (MOZ_UNLIKELY(!buffer)) {
MOZ_CRASH("Out of memory atomizing"); MOZ_CRASH("Out of memory atomizing");
} }

View file

@ -146,9 +146,9 @@ macro_rules! constant_conversion {
}; };
} }
/// An intermediate check for avoiding a copy and having an `nsStringBuffer` /// An intermediate check for avoiding a copy and having an `StringBuffer` refcount increment
/// refcount increment instead when both `self` and `other` are `nsACString`s, /// instead when both `self` and `other` are `nsACString`s, `other` is entirely ASCII and all old
/// `other` is entirely ASCII and all old data in `self` is discarded. /// data in `self` is discarded.
/// ///
/// `$name` is the name of the function to generate /// `$name` is the name of the function to generate
/// `$impl` is the underlying conversion that takes a slice and that is used /// `$impl` is the underlying conversion that takes a slice and that is used

View file

@ -18,7 +18,6 @@ EXPORTS += [
"nsPromiseFlatString.h", "nsPromiseFlatString.h",
"nsReadableUtils.h", "nsReadableUtils.h",
"nsString.h", "nsString.h",
"nsStringBuffer.h",
"nsStringFlags.h", "nsStringFlags.h",
"nsStringFwd.h", "nsStringFwd.h",
"nsStringIterator.h", "nsStringIterator.h",
@ -42,7 +41,6 @@ EXPORTS.mozilla += [
UNIFIED_SOURCES += [ UNIFIED_SOURCES += [
"nsASCIIMask.cpp", "nsASCIIMask.cpp",
"nsReadableUtils.cpp", "nsReadableUtils.cpp",
"nsStringBuffer.cpp",
"nsTDependentString.cpp", "nsTDependentString.cpp",
"nsTDependentSubstring.cpp", "nsTDependentSubstring.cpp",
"nsTextFormatter.cpp", "nsTextFormatter.cpp",

View file

@ -197,7 +197,7 @@ inline void LossyAppendUTF16toASCII(mozilla::Span<const char16_t> aSource,
// Latin1 to UTF-8 // Latin1 to UTF-8
// Interpret each incoming unsigned byte value as a Unicode scalar value (not // Interpret each incoming unsigned byte value as a Unicode scalar value (not
// windows-1252!). // windows-1252!).
// If the input is ASCII, the heap-allocated nsStringBuffer is shared if // If the input is ASCII, the heap-allocated mozilla::StringBuffer is shared if
// possible. // possible.
[[nodiscard]] inline bool CopyLatin1toUTF8(const nsACString& aSource, [[nodiscard]] inline bool CopyLatin1toUTF8(const nsACString& aSource,
@ -231,7 +231,7 @@ inline void AppendLatin1toUTF8(const nsACString& aSource, nsACString& aDest) {
// points above U+00FF, memory-safely produces garbage in release builds and // points above U+00FF, memory-safely produces garbage in release builds and
// asserts in debug builds. The nature of the garbage may differ // asserts in debug builds. The nature of the garbage may differ
// based on CPU architecture and must not be relied upon. // based on CPU architecture and must not be relied upon.
// If the input is ASCII, the heap-allocated nsStringBuffer is shared if // If the input is ASCII, the heap-allocated mozilla::StringBuffer is shared if
// possible. // possible.
[[nodiscard]] inline bool LossyCopyUTF8toLatin1(const nsACString& aSource, [[nodiscard]] inline bool LossyCopyUTF8toLatin1(const nsACString& aSource,

View file

@ -1,70 +0,0 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsStringBuffer.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/RefPtr.h"
template <typename CharT>
static already_AddRefed<nsStringBuffer> DoCreate(const CharT* aData,
size_t aLength) {
RefPtr<nsStringBuffer> buffer =
nsStringBuffer::Alloc((aLength + 1) * sizeof(CharT));
if (MOZ_UNLIKELY(!buffer)) {
return nullptr;
}
auto* data = reinterpret_cast<CharT*>(buffer->Data());
memcpy(data, aData, aLength * sizeof(CharT));
data[aLength] = 0;
return buffer.forget();
}
already_AddRefed<nsStringBuffer> nsStringBuffer::Create(const char* aData,
size_t aLength) {
return DoCreate(aData, aLength);
}
already_AddRefed<nsStringBuffer> nsStringBuffer::Create(const char16_t* aData,
size_t aLength) {
return DoCreate(aData, aLength);
}
nsStringBuffer* nsStringBuffer::Realloc(nsStringBuffer* aHdr, size_t aSize) {
MOZ_ASSERT(aSize != 0, "zero capacity allocation not allowed");
MOZ_ASSERT(sizeof(nsStringBuffer) + aSize <= size_t(uint32_t(-1)) &&
sizeof(nsStringBuffer) + aSize > aSize,
"mStorageSize will truncate");
// no point in trying to save ourselves if we hit this assertion
MOZ_ASSERT(!aHdr->IsReadonly(), "|Realloc| attempted on readonly string");
// Treat this as a release and addref for refcounting purposes, since we
// just asserted that the refcount is 1. If we don't do that, refcount
// logging will claim we've leaked all sorts of stuff.
{
mozilla::detail::RefCountLogger::ReleaseLogger logger(aHdr);
logger.logRelease(0);
}
aHdr = (nsStringBuffer*)realloc(aHdr, sizeof(nsStringBuffer) + aSize);
if (aHdr) {
mozilla::detail::RefCountLogger::logAddRef(aHdr, 1);
aHdr->mStorageSize = aSize;
}
return aHdr;
}
size_t nsStringBuffer::SizeOfIncludingThisIfUnshared(
mozilla::MallocSizeOf aMallocSizeOf) const {
return IsReadonly() ? 0 : aMallocSizeOf(this);
}
size_t nsStringBuffer::SizeOfIncludingThisEvenIfShared(
mozilla::MallocSizeOf aMallocSizeOf) const {
return aMallocSizeOf(this);
}

View file

@ -14,7 +14,7 @@
#include "mozilla/Char16.h" #include "mozilla/Char16.h"
#include "mozilla/CheckedInt.h" #include "mozilla/CheckedInt.h"
#include "mozilla/fallible.h" #include "mozilla/fallible.h"
#include "nsStringBuffer.h" #include "mozilla/StringBuffer.h"
#include "nsStringFlags.h" #include "nsStringFlags.h"
#include "nsStringFwd.h" #include "nsStringFwd.h"
#include "nsStringIterator.h" #include "nsStringIterator.h"
@ -74,9 +74,9 @@ class nsTStringLengthStorage {
"nsTString's maximum length, including the trailing null, must fit " "nsTString's maximum length, including the trailing null, must fit "
"within `int32_t`, as callers will cast to `int32_t` occasionally"); "within `int32_t`, as callers will cast to `int32_t` occasionally");
static_assert(((CheckedInt<uint32_t>{kMax} + 1) * sizeof(T) + static_assert(((CheckedInt<uint32_t>{kMax} + 1) * sizeof(T) +
sizeof(nsStringBuffer)) sizeof(mozilla::StringBuffer))
.isValid(), .isValid(),
"Math required to allocate a nsStringBuffer for a " "Math required to allocate a mozilla::StringBuffer for a "
"maximum-capacity string must not overflow uint32_t"); "maximum-capacity string must not overflow uint32_t");
// Implicit conversion and assignment from `size_t` which assert that the // Implicit conversion and assignment from `size_t` which assert that the

View file

@ -50,7 +50,7 @@ char16_t* const nsCharTraits<char16_t>::sEmptyBuffer =
static void ReleaseData(void* aData, nsAString::DataFlags aFlags) { static void ReleaseData(void* aData, nsAString::DataFlags aFlags) {
if (aFlags & nsAString::DataFlags::REFCOUNTED) { if (aFlags & nsAString::DataFlags::REFCOUNTED) {
nsStringBuffer::FromData(aData)->Release(); mozilla::StringBuffer::FromData(aData)->Release();
} else if (aFlags & nsAString::DataFlags::OWNED) { } else if (aFlags & nsAString::DataFlags::OWNED) {
// Treat this as destruction of a "StringAdopt" object for leak // Treat this as destruction of a "StringAdopt" object for leak
// tracking purposes. // tracking purposes.
@ -172,8 +172,8 @@ auto nsTSubstring<T>::StartBulkWriteImpl(size_type aCapacity,
// If |aCapacity > kMaxCapacity|, then our doubling algorithm may not be // If |aCapacity > kMaxCapacity|, then our doubling algorithm may not be
// able to allocate it. Just bail out in cases like that. We don't want // able to allocate it. Just bail out in cases like that. We don't want
// to be allocating 2GB+ strings anyway. // to be allocating 2GB+ strings anyway.
static_assert((sizeof(nsStringBuffer) & 0x1) == 0, static_assert((sizeof(mozilla::StringBuffer) & 0x1) == 0,
"bad size for nsStringBuffer"); "bad size for mozilla::StringBuffer");
if (MOZ_UNLIKELY(!this->CheckCapacity(aCapacity))) { if (MOZ_UNLIKELY(!this->CheckCapacity(aCapacity))) {
return mozilla::Err(NS_ERROR_OUT_OF_MEMORY); return mozilla::Err(NS_ERROR_OUT_OF_MEMORY);
} }
@ -184,10 +184,10 @@ auto nsTSubstring<T>::StartBulkWriteImpl(size_type aCapacity,
// least 1.125, rounding up to the nearest MiB. // least 1.125, rounding up to the nearest MiB.
const size_type slowGrowthThreshold = 8 * 1024 * 1024; const size_type slowGrowthThreshold = 8 * 1024 * 1024;
// nsStringBuffer allocates sizeof(nsStringBuffer) + passed size, and // mozilla::StringBuffer allocates sizeof(mozilla::StringBuffer) + passed
// storageSize below wants extra 1 * sizeof(char_type). // size, and storageSize below wants extra 1 * sizeof(char_type).
const size_type neededExtraSpace = const size_type neededExtraSpace =
sizeof(nsStringBuffer) / sizeof(char_type) + 1; sizeof(mozilla::StringBuffer) / sizeof(char_type) + 1;
size_type temp; size_type temp;
if (aCapacity >= slowGrowthThreshold) { if (aCapacity >= slowGrowthThreshold) {
@ -196,8 +196,8 @@ auto nsTSubstring<T>::StartBulkWriteImpl(size_type aCapacity,
temp = XPCOM_MAX(aCapacity, minNewCapacity) + neededExtraSpace; temp = XPCOM_MAX(aCapacity, minNewCapacity) + neededExtraSpace;
// Round up to the next multiple of MiB, but ensure the expected // Round up to the next multiple of MiB, but ensure the expected
// capacity doesn't include the extra space required by nsStringBuffer // capacity doesn't include the extra space required by
// and null-termination. // mozilla::StringBuffer and null-termination.
const size_t MiB = 1 << 20; const size_t MiB = 1 << 20;
temp = (MiB * ((temp + MiB - 1) / MiB)) - neededExtraSpace; temp = (MiB * ((temp + MiB - 1) / MiB)) - neededExtraSpace;
} else { } else {
@ -222,7 +222,8 @@ auto nsTSubstring<T>::StartBulkWriteImpl(size_type aCapacity,
// Since we allocate only by powers of 2 we always fit into a full // Since we allocate only by powers of 2 we always fit into a full
// mozjemalloc bucket, it's not useful to use realloc, which may spend // mozjemalloc bucket, it's not useful to use realloc, which may spend
// time uselessly copying too much. // time uselessly copying too much.
nsStringBuffer* newHdr = nsStringBuffer::Alloc(storageSize).take(); mozilla::StringBuffer* newHdr =
mozilla::StringBuffer::Alloc(storageSize).take();
if (newHdr) { if (newHdr) {
newData = (char_type*)newHdr->Data(); newData = (char_type*)newHdr->Data();
} else if (shrinking) { } else if (shrinking) {
@ -336,7 +337,7 @@ typename nsTSubstring<T>::size_type nsTSubstring<T>::Capacity() const {
size_type capacity; size_type capacity;
if (this->mDataFlags & DataFlags::REFCOUNTED) { if (this->mDataFlags & DataFlags::REFCOUNTED) {
// if the string is readonly, then we pretend that it has no capacity. // if the string is readonly, then we pretend that it has no capacity.
nsStringBuffer* hdr = nsStringBuffer::FromData(this->mData); mozilla::StringBuffer* hdr = mozilla::StringBuffer::FromData(this->mData);
if (hdr->IsReadonly()) { if (hdr->IsReadonly()) {
capacity = 0; capacity = 0;
} else { } else {
@ -365,7 +366,7 @@ bool nsTSubstring<T>::EnsureMutable(size_type aNewLen) {
return true; return true;
} }
if ((this->mDataFlags & DataFlags::REFCOUNTED) && if ((this->mDataFlags & DataFlags::REFCOUNTED) &&
!nsStringBuffer::FromData(this->mData)->IsReadonly()) { !mozilla::StringBuffer::FromData(this->mData)->IsReadonly()) {
return true; return true;
} }
@ -404,9 +405,9 @@ void nsTSubstring<T>::Assign(const char_type* aData, size_type aLength) {
} }
template <typename T> template <typename T>
void nsTSubstring<T>::Assign(already_AddRefed<nsStringBuffer> aBuffer, void nsTSubstring<T>::Assign(already_AddRefed<mozilla::StringBuffer> aBuffer,
size_type aLength) { size_type aLength) {
nsStringBuffer* buffer = aBuffer.take(); mozilla::StringBuffer* buffer = aBuffer.take();
auto* data = reinterpret_cast<char_type*>(buffer->Data()); auto* data = reinterpret_cast<char_type*>(buffer->Data());
MOZ_DIAGNOSTIC_ASSERT(data[aLength] == char_type(0), MOZ_DIAGNOSTIC_ASSERT(data[aLength] == char_type(0),
"data should be null terminated"); "data should be null terminated");
@ -517,7 +518,7 @@ bool nsTSubstring<T>::Assign(const self_type& aStr,
DataFlags::TERMINATED | DataFlags::REFCOUNTED); DataFlags::TERMINATED | DataFlags::REFCOUNTED);
// get an owning reference to the this->mData // get an owning reference to the this->mData
nsStringBuffer::FromData(this->mData)->AddRef(); mozilla::StringBuffer::FromData(this->mData)->AddRef();
return true; return true;
} }
if (aStr.mDataFlags & DataFlags::LITERAL) { if (aStr.mDataFlags & DataFlags::LITERAL) {
@ -1236,7 +1237,7 @@ template <typename T>
size_t nsTSubstring<T>::SizeOfExcludingThisIfUnshared( size_t nsTSubstring<T>::SizeOfExcludingThisIfUnshared(
mozilla::MallocSizeOf aMallocSizeOf) const { mozilla::MallocSizeOf aMallocSizeOf) const {
if (this->mDataFlags & DataFlags::REFCOUNTED) { if (this->mDataFlags & DataFlags::REFCOUNTED) {
return nsStringBuffer::FromData(this->mData) return mozilla::StringBuffer::FromData(this->mData)
->SizeOfIncludingThisIfUnshared(aMallocSizeOf); ->SizeOfIncludingThisIfUnshared(aMallocSizeOf);
} }
if (this->mDataFlags & DataFlags::OWNED) { if (this->mDataFlags & DataFlags::OWNED) {
@ -1260,7 +1261,7 @@ size_t nsTSubstring<T>::SizeOfExcludingThisEvenIfShared(
// This is identical to SizeOfExcludingThisIfUnshared except for the // This is identical to SizeOfExcludingThisIfUnshared except for the
// DataFlags::REFCOUNTED case. // DataFlags::REFCOUNTED case.
if (this->mDataFlags & DataFlags::REFCOUNTED) { if (this->mDataFlags & DataFlags::REFCOUNTED) {
return nsStringBuffer::FromData(this->mData) return mozilla::StringBuffer::FromData(this->mData)
->SizeOfIncludingThisEvenIfShared(aMallocSizeOf); ->SizeOfIncludingThisEvenIfShared(aMallocSizeOf);
} }
if (this->mDataFlags & DataFlags::OWNED) { if (this->mDataFlags & DataFlags::OWNED) {

View file

@ -18,7 +18,6 @@
#include "mozilla/Span.h" #include "mozilla/Span.h"
#include "mozilla/Try.h" #include "mozilla/Try.h"
#include "mozilla/Unused.h" #include "mozilla/Unused.h"
#include "nsStringBuffer.h"
#include "nsTStringRepr.h" #include "nsTStringRepr.h"
@ -31,7 +30,6 @@
// memory checking. (Limited to avoid quadratic behavior.) // memory checking. (Limited to avoid quadratic behavior.)
const size_t kNsStringBufferMaxPoison = 16; const size_t kNsStringBufferMaxPoison = 16;
class nsStringBuffer;
template <typename T> template <typename T>
class nsTSubstringSplitter; class nsTSubstringSplitter;
template <typename T> template <typename T>
@ -283,7 +281,7 @@ class BulkWriteHandle final {
template <typename T> template <typename T>
class nsTSubstring : public mozilla::detail::nsTStringRepr<T> { class nsTSubstring : public mozilla::detail::nsTStringRepr<T> {
friend class mozilla::BulkWriteHandle<T>; friend class mozilla::BulkWriteHandle<T>;
friend class nsStringBuffer; friend class mozilla::StringBuffer;
public: public:
typedef nsTSubstring<T> self_type; typedef nsTSubstring<T> self_type;
@ -419,11 +417,11 @@ class nsTSubstring : public mozilla::detail::nsTStringRepr<T> {
[[nodiscard]] bool NS_FASTCALL Assign(const substring_tuple_type&, [[nodiscard]] bool NS_FASTCALL Assign(const substring_tuple_type&,
const fallible_t&); const fallible_t&);
void Assign(nsStringBuffer* aBuffer, size_type aLength) { void Assign(mozilla::StringBuffer* aBuffer, size_type aLength) {
aBuffer->AddRef(); aBuffer->AddRef();
Assign(already_AddRefed<nsStringBuffer>(aBuffer), aLength); Assign(already_AddRefed<mozilla::StringBuffer>(aBuffer), aLength);
} }
void NS_FASTCALL Assign(already_AddRefed<nsStringBuffer> aBuffer, void NS_FASTCALL Assign(already_AddRefed<mozilla::StringBuffer> aBuffer,
size_type aLength); size_type aLength);
#if defined(MOZ_USE_CHAR16_WRAPPER) #if defined(MOZ_USE_CHAR16_WRAPPER)
@ -1155,9 +1153,9 @@ class nsTSubstring : public mozilla::detail::nsTStringRepr<T> {
* If the string uses a reference-counted buffer, this method returns a * If the string uses a reference-counted buffer, this method returns a
* pointer to it without incrementing the buffer's refcount. * pointer to it without incrementing the buffer's refcount.
*/ */
nsStringBuffer* GetStringBuffer() const { mozilla::StringBuffer* GetStringBuffer() const {
if (this->mDataFlags & DataFlags::REFCOUNTED) { if (this->mDataFlags & DataFlags::REFCOUNTED) {
return nsStringBuffer::FromData(this->mData); return mozilla::StringBuffer::FromData(this->mData);
} }
return nullptr; return nullptr;
} }

View file

@ -8,7 +8,6 @@
#include <stdlib.h> #include <stdlib.h>
#include "nsASCIIMask.h" #include "nsASCIIMask.h"
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "nsCRTGlue.h" #include "nsCRTGlue.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"

View file

@ -10,7 +10,7 @@
#include "nsCharSeparatedTokenizer.h" #include "nsCharSeparatedTokenizer.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h" #include "mozilla/StringBuffer.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "nsCRTGlue.h" #include "nsCRTGlue.h"
#include "mozilla/RefPtr.h" #include "mozilla/RefPtr.h"
@ -44,6 +44,7 @@ using mozilla::Maybe;
using mozilla::Nothing; using mozilla::Nothing;
using mozilla::Some; using mozilla::Some;
using mozilla::Span; using mozilla::Span;
using mozilla::StringBuffer;
#define TestExample1 \ #define TestExample1 \
"Sed ut perspiciatis unde omnis iste natus error sit voluptatem " \ "Sed ut perspiciatis unde omnis iste natus error sit voluptatem " \
@ -1172,12 +1173,12 @@ TEST_F(Strings, rfindcharinset) {
TEST_F(Strings, stringbuffer) { TEST_F(Strings, stringbuffer) {
const char kData[] = "hello world"; const char kData[] = "hello world";
RefPtr<nsStringBuffer> buf; RefPtr<StringBuffer> buf;
buf = nsStringBuffer::Alloc(sizeof(kData)); buf = StringBuffer::Alloc(sizeof(kData));
EXPECT_TRUE(!!buf); EXPECT_TRUE(!!buf);
buf = nsStringBuffer::Alloc(sizeof(kData)); buf = StringBuffer::Alloc(sizeof(kData));
EXPECT_TRUE(!!buf); EXPECT_TRUE(!!buf);
char* data = (char*)buf->Data(); char* data = (char*)buf->Data();
memcpy(data, kData, sizeof(kData)); memcpy(data, kData, sizeof(kData));
@ -1185,7 +1186,7 @@ TEST_F(Strings, stringbuffer) {
nsCString str; nsCString str;
str.Assign(buf, sizeof(kData) - 1); str.Assign(buf, sizeof(kData) - 1);
nsStringBuffer* buf2 = str.GetStringBuffer(); StringBuffer* buf2 = str.GetStringBuffer();
EXPECT_EQ(buf, buf2); EXPECT_EQ(buf, buf2);
} }

View file

@ -9,7 +9,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "nsString.h" #include "nsString.h"
#include "nsStringBuffer.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "UTFStrings.h" #include "UTFStrings.h"
#include "nsUnicharUtils.h" #include "nsUnicharUtils.h"