Bug 1292618: Tidy up nsStyleContent's API now allocations are infallible. r=heycam

MozReview-Commit-ID: BrHn4RiEWeg
This commit is contained in:
Emilio Cobos Álvarez 2016-08-16 13:57:31 -07:00
Родитель 0011f2bc39
Коммит bcc13a32eb
6 изменённых файлов: 165 добавлений и 276 удалений

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

@ -226,32 +226,31 @@ nsCounterManager::AddCounterResetsAndIncrements(nsIFrame *aFrame)
int32_t i, i_end;
bool dirty = false;
for (i = 0, i_end = styleContent->CounterResetCount(); i != i_end; ++i)
dirty |= AddResetOrIncrement(aFrame, i,
styleContent->GetCounterResetAt(i),
nsCounterChangeNode::RESET);
dirty |= AddResetOrIncrement(aFrame, i, styleContent->CounterResetAt(i),
nsCounterChangeNode::RESET);
for (i = 0, i_end = styleContent->CounterIncrementCount(); i != i_end; ++i)
dirty |= AddResetOrIncrement(aFrame, i,
styleContent->GetCounterIncrementAt(i),
nsCounterChangeNode::INCREMENT);
dirty |=
AddResetOrIncrement(aFrame, i, styleContent->CounterIncrementAt(i),
nsCounterChangeNode::INCREMENT);
return dirty;
}
bool
nsCounterManager::AddResetOrIncrement(nsIFrame *aFrame, int32_t aIndex,
const nsStyleCounterData *aCounterData,
nsCounterManager::AddResetOrIncrement(nsIFrame* aFrame, int32_t aIndex,
const nsStyleCounterData& aCounterData,
nsCounterNode::Type aType)
{
nsCounterChangeNode *node =
new nsCounterChangeNode(aFrame, aType, aCounterData->mValue, aIndex);
nsCounterChangeNode* node =
new nsCounterChangeNode(aFrame, aType, aCounterData.mValue, aIndex);
nsCounterList *counterList = CounterListFor(aCounterData->mCounter);
nsCounterList* counterList = CounterListFor(aCounterData.mCounter);
counterList->Insert(node);
if (!counterList->IsLast(node)) {
// Tell the caller it's responsible for recalculating the entire
// list.
counterList->SetDirty();
return true;
counterList->Insert(node);
if (!counterList->IsLast(node)) {
// Tell the caller it's responsible for recalculating the entire
// list.
counterList->SetDirty();
return true;
}
// Don't call Calc() if the list is already dirty -- it'll be recalculated

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

@ -271,11 +271,11 @@ public:
private:
// for |AddCounterResetsAndIncrements| only
bool AddResetOrIncrement(nsIFrame *aFrame, int32_t aIndex,
const nsStyleCounterData *aCounterData,
nsCounterNode::Type aType);
bool AddResetOrIncrement(nsIFrame* aFrame, int32_t aIndex,
const nsStyleCounterData& aCounterData,
nsCounterNode::Type aType);
nsClassHashtable<nsStringHashKey, nsCounterList> mNames;
nsClassHashtable<nsStringHashKey, nsCounterList> mNames;
};
#endif /* nsCounterManager_h_ */

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

@ -1197,11 +1197,11 @@ nsComputedDOMStyle::DoGetCounterIncrement()
RefPtr<nsROCSSPrimitiveValue> name = new nsROCSSPrimitiveValue;
RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
const nsStyleCounterData *data = content->GetCounterIncrementAt(i);
const nsStyleCounterData& data = content->CounterIncrementAt(i);
nsAutoString escaped;
nsStyleUtil::AppendEscapedCSSIdent(data->mCounter, escaped);
nsStyleUtil::AppendEscapedCSSIdent(data.mCounter, escaped);
name->SetString(escaped);
value->SetNumber(data->mValue); // XXX This should really be integer
value->SetNumber(data.mValue); // XXX This should really be integer
valueList->AppendCSSValue(name.forget());
valueList->AppendCSSValue(value.forget());
@ -1441,11 +1441,11 @@ nsComputedDOMStyle::DoGetCounterReset()
RefPtr<nsROCSSPrimitiveValue> name = new nsROCSSPrimitiveValue;
RefPtr<nsROCSSPrimitiveValue> value = new nsROCSSPrimitiveValue;
const nsStyleCounterData *data = content->GetCounterResetAt(i);
const nsStyleCounterData& data = content->CounterResetAt(i);
nsAutoString escaped;
nsStyleUtil::AppendEscapedCSSIdent(data->mCounter, escaped);
nsStyleUtil::AppendEscapedCSSIdent(data.mCounter, escaped);
name->SetString(escaped);
value->SetNumber(data->mValue); // XXX This should really be integer
value->SetNumber(data.mValue); // XXX This should really be integer
valueList->AppendCSSValue(name.forget());
valueList->AppendCSSValue(value.forget());

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

@ -8863,10 +8863,9 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
case eCSSUnit_Inherit:
conditions.SetUncacheable();
count = parentContent->ContentCount();
if (NS_SUCCEEDED(content->AllocateContents(count))) {
while (0 < count--) {
content->ContentAt(count) = parentContent->ContentAt(count);
}
content->AllocateContents(count);
while (0 < count--) {
content->ContentAt(count) = parentContent->ContentAt(count);
}
break;
@ -8883,66 +8882,62 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
case eCSSUnit_List:
case eCSSUnit_ListDep: {
const nsCSSValueList* contentValueList = contentValue->GetListValue();
count = 0;
while (contentValueList) {
count++;
contentValueList = contentValueList->mNext;
}
if (NS_SUCCEEDED(content->AllocateContents(count))) {
const nsAutoString nullStr;
count = 0;
contentValueList = contentValue->GetListValue();
while (contentValueList) {
const nsCSSValue& value = contentValueList->mValue;
nsCSSUnit unit = value.GetUnit();
nsStyleContentType type;
nsStyleContentData &data = content->ContentAt(count++);
switch (unit) {
case eCSSUnit_String: type = eStyleContentType_String; break;
case eCSSUnit_Image: type = eStyleContentType_Image; break;
case eCSSUnit_Attr: type = eStyleContentType_Attr; break;
case eCSSUnit_Counter: type = eStyleContentType_Counter; break;
case eCSSUnit_Counters: type = eStyleContentType_Counters; break;
case eCSSUnit_Enumerated:
switch (value.GetIntValue()) {
case NS_STYLE_CONTENT_OPEN_QUOTE:
type = eStyleContentType_OpenQuote; break;
case NS_STYLE_CONTENT_CLOSE_QUOTE:
type = eStyleContentType_CloseQuote; break;
case NS_STYLE_CONTENT_NO_OPEN_QUOTE:
type = eStyleContentType_NoOpenQuote; break;
case NS_STYLE_CONTENT_NO_CLOSE_QUOTE:
type = eStyleContentType_NoCloseQuote; break;
default:
NS_ERROR("bad content value");
type = eStyleContentType_Uninitialized;
}
break;
default:
NS_ERROR("bad content type");
type = eStyleContentType_Uninitialized;
}
data.mType = type;
if (type == eStyleContentType_Image) {
SetImageRequest([&](imgRequestProxy* req) {
data.SetImage(req);
}, mPresContext, value);
}
else if (type <= eStyleContentType_Attr) {
value.GetStringValue(buffer);
data.mContent.mString = NS_strdup(buffer.get());
}
else if (type <= eStyleContentType_Counters) {
data.mContent.mCounters = value.GetArrayValue();
data.mContent.mCounters->AddRef();
}
else {
data.mContent.mString = nullptr;
}
contentValueList = contentValueList->mNext;
count = 0;
while (contentValueList) {
count++;
contentValueList = contentValueList->mNext;
}
content->AllocateContents(count);
const nsAutoString nullStr;
count = 0;
contentValueList = contentValue->GetListValue();
while (contentValueList) {
const nsCSSValue& value = contentValueList->mValue;
nsCSSUnit unit = value.GetUnit();
nsStyleContentType type;
nsStyleContentData &data = content->ContentAt(count++);
switch (unit) {
case eCSSUnit_String: type = eStyleContentType_String; break;
case eCSSUnit_Image: type = eStyleContentType_Image; break;
case eCSSUnit_Attr: type = eStyleContentType_Attr; break;
case eCSSUnit_Counter: type = eStyleContentType_Counter; break;
case eCSSUnit_Counters: type = eStyleContentType_Counters; break;
case eCSSUnit_Enumerated:
switch (value.GetIntValue()) {
case NS_STYLE_CONTENT_OPEN_QUOTE:
type = eStyleContentType_OpenQuote; break;
case NS_STYLE_CONTENT_CLOSE_QUOTE:
type = eStyleContentType_CloseQuote; break;
case NS_STYLE_CONTENT_NO_OPEN_QUOTE:
type = eStyleContentType_NoOpenQuote; break;
case NS_STYLE_CONTENT_NO_CLOSE_QUOTE:
type = eStyleContentType_NoCloseQuote; break;
default:
NS_ERROR("bad content value");
type = eStyleContentType_Uninitialized;
}
break;
default:
NS_ERROR("bad content type");
type = eStyleContentType_Uninitialized;
}
break;
data.mType = type;
if (type == eStyleContentType_Image) {
SetImageRequest([&](imgRequestProxy* req) {
data.SetImage(req);
}, mPresContext, value);
} else if (type <= eStyleContentType_Attr) {
value.GetStringValue(buffer);
data.mContent.mString = NS_strdup(buffer.get());
} else if (type <= eStyleContentType_Counters) {
data.mContent.mCounters = value.GetArrayValue();
data.mContent.mCounters->AddRef();
} else {
data.mContent.mString = nullptr;
}
contentValueList = contentValueList->mNext;
}
break;
}
default:
@ -8965,12 +8960,10 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
case eCSSUnit_Inherit:
conditions.SetUncacheable();
count = parentContent->CounterIncrementCount();
if (NS_SUCCEEDED(content->AllocateCounterIncrements(count))) {
while (0 < count--) {
const nsStyleCounterData *data =
parentContent->GetCounterIncrementAt(count);
content->SetCounterIncrementAt(count, data->mCounter, data->mValue);
}
content->AllocateCounterIncrements(count);
while (count--) {
const nsStyleCounterData& data = parentContent->CounterIncrementAt(count);
content->SetCounterIncrementAt(count, data.mCounter, data.mValue);
}
break;
@ -8981,9 +8974,7 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
MOZ_ASSERT(ourIncrement->mXValue.GetUnit() == eCSSUnit_Ident,
"unexpected value unit");
count = ListLength(ourIncrement);
if (NS_FAILED(content->AllocateCounterIncrements(count))) {
break;
}
content->AllocateCounterIncrements(count);
count = 0;
for (const nsCSSValuePairList* p = ourIncrement; p; p = p->mNext, count++) {
@ -9018,12 +9009,10 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
case eCSSUnit_Inherit:
conditions.SetUncacheable();
count = parentContent->CounterResetCount();
if (NS_SUCCEEDED(content->AllocateCounterResets(count))) {
while (0 < count--) {
const nsStyleCounterData *data =
parentContent->GetCounterResetAt(count);
content->SetCounterResetAt(count, data->mCounter, data->mValue);
}
content->AllocateCounterResets(count);
while (0 < count--) {
const nsStyleCounterData& data = parentContent->CounterResetAt(count);
content->SetCounterResetAt(count, data.mCounter, data.mValue);
}
break;
@ -9034,10 +9023,7 @@ nsRuleNode::ComputeContentData(void* aStartStruct,
MOZ_ASSERT(ourReset->mXValue.GetUnit() == eCSSUnit_Ident,
"unexpected value unit");
count = ListLength(ourReset);
if (NS_FAILED(content->AllocateCounterResets(count))) {
break;
}
content->AllocateCounterResets(count);
count = 0;
for (const nsCSSValuePairList* p = ourReset; p; p = p->mNext, count++) {
int32_t reset;

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

@ -3389,6 +3389,7 @@ nsStyleVisibility::CalcDifference(const nsStyleVisibility& aNewData) const
nsStyleContentData::~nsStyleContentData()
{
MOZ_COUNT_DTOR(nsStyleContentData);
MOZ_ASSERT(!mImageTracked,
"nsStyleContentData being destroyed while still tracking image!");
if (mType == eStyleContentType_Image) {
@ -3401,15 +3402,8 @@ nsStyleContentData::~nsStyleContentData()
}
}
nsStyleContentData&
nsStyleContentData::operator=(const nsStyleContentData& aOther)
nsStyleContentData::nsStyleContentData(const nsStyleContentData& aOther)
{
if (this == &aOther) {
return *this;
}
this->~nsStyleContentData();
new (this) nsStyleContentData();
mType = aOther.mType;
if (mType == eStyleContentType_Image) {
mContent.mImage = aOther.mContent.mImage;
@ -3423,6 +3417,17 @@ nsStyleContentData::operator=(const nsStyleContentData& aOther)
} else {
mContent.mString = nullptr;
}
}
nsStyleContentData&
nsStyleContentData::operator=(const nsStyleContentData& aOther)
{
if (this == &aOther) {
return *this;
}
this->~nsStyleContentData();
new (this) nsStyleContentData(aOther);
return *this;
}
@ -3503,12 +3508,6 @@ nsStyleContentData::UntrackImage(nsPresContext* aContext)
nsStyleContent::nsStyleContent(StyleStructContext aContext)
: mMarkerOffset(eStyleUnit_Auto)
, mContents(nullptr)
, mIncrements(nullptr)
, mResets(nullptr)
, mContentCount(0)
, mIncrementCount(0)
, mResetCount(0)
{
MOZ_COUNT_CTOR(nsStyleContent);
}
@ -3516,61 +3515,29 @@ nsStyleContent::nsStyleContent(StyleStructContext aContext)
nsStyleContent::~nsStyleContent()
{
MOZ_COUNT_DTOR(nsStyleContent);
DELETE_ARRAY_IF(mContents);
DELETE_ARRAY_IF(mIncrements);
DELETE_ARRAY_IF(mResets);
}
void
nsStyleContent::Destroy(nsPresContext* aContext)
{
// Unregister any images we might have with the document.
for (uint32_t i = 0; i < mContentCount; ++i) {
if ((mContents[i].mType == eStyleContentType_Image) &&
mContents[i].mContent.mImage) {
mContents[i].UntrackImage(aContext);
for (auto& content : mContents) {
if (content.mType == eStyleContentType_Image && content.mContent.mImage) {
content.UntrackImage(aContext);
}
}
this->~nsStyleContent();
aContext->PresShell()->
FreeByObjectID(eArenaObjectID_nsStyleContent, this);
aContext->PresShell()->FreeByObjectID(eArenaObjectID_nsStyleContent, this);
}
nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
: mMarkerOffset(aSource.mMarkerOffset)
, mContents(nullptr)
, mIncrements(nullptr)
, mResets(nullptr)
, mContentCount(0)
, mIncrementCount(0)
, mResetCount(0)
, mContents(aSource.mContents)
, mIncrements(aSource.mIncrements)
, mResets(aSource.mResets)
{
MOZ_COUNT_CTOR(nsStyleContent);
uint32_t index;
if (NS_SUCCEEDED(AllocateContents(aSource.ContentCount()))) {
for (index = 0; index < mContentCount; index++) {
ContentAt(index) = aSource.ContentAt(index);
}
}
if (NS_SUCCEEDED(AllocateCounterIncrements(aSource.CounterIncrementCount()))) {
for (index = 0; index < mIncrementCount; index++) {
const nsStyleCounterData *data = aSource.GetCounterIncrementAt(index);
mIncrements[index].mCounter = data->mCounter;
mIncrements[index].mValue = data->mValue;
}
}
if (NS_SUCCEEDED(AllocateCounterResets(aSource.CounterResetCount()))) {
for (index = 0; index < mResetCount; index++) {
const nsStyleCounterData *data = aSource.GetCounterResetAt(index);
mResets[index].mCounter = data->mCounter;
mResets[index].mValue = data->mValue;
}
}
}
nsChangeHint
@ -3588,62 +3555,22 @@ nsStyleContent::CalcDifference(const nsStyleContent& aNewData) const
// 'content' property, then we will need to revisit the optimization
// in ReResolveStyleContext.
if (mContentCount != aNewData.mContentCount ||
mIncrementCount != aNewData.mIncrementCount ||
mResetCount != aNewData.mResetCount) {
// Unfortunately we need to reframe even if the content lengths are the same;
// a simple reflow will not pick up different text or different image URLs,
// since we set all that up in the CSSFrameConstructor
if (mContents != aNewData.mContents ||
mIncrements != aNewData.mIncrements ||
mResets != aNewData.mResets) {
return nsChangeHint_ReconstructFrame;
}
uint32_t ix = mContentCount;
while (0 < ix--) {
if (mContents[ix] != aNewData.mContents[ix]) {
// Unfortunately we need to reframe here; a simple reflow
// will not pick up different text or different image URLs,
// since we set all that up in the CSSFrameConstructor
return nsChangeHint_ReconstructFrame;
}
}
ix = mIncrementCount;
while (0 < ix--) {
if ((mIncrements[ix].mValue != aNewData.mIncrements[ix].mValue) ||
(mIncrements[ix].mCounter != aNewData.mIncrements[ix].mCounter)) {
return nsChangeHint_ReconstructFrame;
}
}
ix = mResetCount;
while (0 < ix--) {
if ((mResets[ix].mValue != aNewData.mResets[ix].mValue) ||
(mResets[ix].mCounter != aNewData.mResets[ix].mCounter)) {
return nsChangeHint_ReconstructFrame;
}
}
if (mMarkerOffset != aNewData.mMarkerOffset) {
return NS_STYLE_HINT_REFLOW;
}
return nsChangeHint(0);
}
nsresult
nsStyleContent::AllocateContents(uint32_t aCount)
{
// We need to run the destructors of the elements of mContents, so we
// delete and reallocate even if aCount == mContentCount. (If
// nsStyleContentData had its members private and managed their
// ownership on setting, we wouldn't need this, but that seems
// unnecessary at this point.)
DELETE_ARRAY_IF(mContents);
if (aCount) {
mContents = new nsStyleContentData[aCount];
if (! mContents) {
mContentCount = 0;
return NS_ERROR_OUT_OF_MEMORY;
}
}
mContentCount = aCount;
return NS_OK;
}
// --------------------
// nsStyleTextReset
//

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

@ -3161,7 +3161,11 @@ struct nsStyleContentData
#ifdef DEBUG
, mImageTracked(false)
#endif
{ mContent.mString = nullptr; }
{
MOZ_COUNT_CTOR(nsStyleContentData);
mContent.mString = nullptr;
}
nsStyleContentData(const nsStyleContentData&);
~nsStyleContentData();
nsStyleContentData& operator=(const nsStyleContentData& aOther);
@ -3181,19 +3185,22 @@ struct nsStyleContentData
MOZ_ASSERT(mType == eStyleContentType_Image, "Wrong type!");
NS_IF_ADDREF(mContent.mImage = aRequest);
}
private:
nsStyleContentData(const nsStyleContentData&); // not to be implemented
};
struct nsStyleCounterData
{
nsString mCounter;
int32_t mValue;
bool operator==(const nsStyleCounterData& aOther) const {
return mValue == aOther.mValue && mCounter == aOther.mCounter;
}
bool operator!=(const nsStyleCounterData& aOther) const {
return !(*this == aOther);
}
};
#define DELETE_ARRAY_IF(array) if (array) { delete[] array; array = nullptr; }
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent
{
explicit nsStyleContent(StyleStructContext aContext);
@ -3220,90 +3227,60 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent
nsChangeHint_ClearAncestorIntrinsics;
}
uint32_t ContentCount() const { return mContentCount; } // [reset]
uint32_t ContentCount() const { return mContents.Length(); } // [reset]
const nsStyleContentData& ContentAt(uint32_t aIndex) const {
NS_ASSERTION(aIndex < mContentCount, "out of range");
return mContents[aIndex];
}
nsStyleContentData& ContentAt(uint32_t aIndex) {
NS_ASSERTION(aIndex < mContentCount, "out of range");
return mContents[aIndex];
nsStyleContentData& ContentAt(uint32_t aIndex) { return mContents[aIndex]; }
void AllocateContents(uint32_t aCount) {
// We need to run the destructors of the elements of mContents, so we
// delete and reallocate even if aCount == mContentCount. (If
// nsStyleContentData had its members private and managed their
// ownership on setting, we wouldn't need this, but that seems
// unnecessary at this point.)
mContents.Clear();
mContents.SetLength(aCount);
}
nsresult AllocateContents(uint32_t aCount);
uint32_t CounterIncrementCount() const { return mIncrementCount; } // [reset]
const nsStyleCounterData* GetCounterIncrementAt(uint32_t aIndex) const {
NS_ASSERTION(aIndex < mIncrementCount, "out of range");
return &mIncrements[aIndex];
uint32_t CounterIncrementCount() const { return mIncrements.Length(); } // [reset]
const nsStyleCounterData& CounterIncrementAt(uint32_t aIndex) const {
return mIncrements[aIndex];
}
nsresult AllocateCounterIncrements(uint32_t aCount) {
if (aCount != mIncrementCount) {
DELETE_ARRAY_IF(mIncrements);
if (aCount) {
mIncrements = new nsStyleCounterData[aCount];
if (! mIncrements) {
mIncrementCount = 0;
return NS_ERROR_OUT_OF_MEMORY;
}
}
mIncrementCount = aCount;
}
return NS_OK;
void AllocateCounterIncrements(uint32_t aCount) {
mIncrements.Clear();
mIncrements.SetLength(aCount);
}
nsresult SetCounterIncrementAt(uint32_t aIndex, const nsString& aCounter, int32_t aIncrement) {
if (aIndex < mIncrementCount) {
mIncrements[aIndex].mCounter = aCounter;
mIncrements[aIndex].mValue = aIncrement;
return NS_OK;
}
return NS_ERROR_ILLEGAL_VALUE;
void SetCounterIncrementAt(uint32_t aIndex, const nsString& aCounter, int32_t aIncrement) {
mIncrements[aIndex].mCounter = aCounter;
mIncrements[aIndex].mValue = aIncrement;
}
uint32_t CounterResetCount() const { return mResetCount; } // [reset]
const nsStyleCounterData* GetCounterResetAt(uint32_t aIndex) const {
NS_ASSERTION(aIndex < mResetCount, "out of range");
return &mResets[aIndex];
uint32_t CounterResetCount() const { return mResets.Length(); } // [reset]
const nsStyleCounterData& CounterResetAt(uint32_t aIndex) const {
return mResets[aIndex];
}
nsresult AllocateCounterResets(uint32_t aCount) {
if (aCount != mResetCount) {
DELETE_ARRAY_IF(mResets);
if (aCount) {
mResets = new nsStyleCounterData[aCount];
if (! mResets) {
mResetCount = 0;
return NS_ERROR_OUT_OF_MEMORY;
}
}
mResetCount = aCount;
}
return NS_OK;
void AllocateCounterResets(uint32_t aCount) {
mResets.Clear();
mResets.SetLength(aCount);
}
nsresult SetCounterResetAt(uint32_t aIndex, const nsString& aCounter, int32_t aValue) {
if (aIndex < mResetCount) {
mResets[aIndex].mCounter = aCounter;
mResets[aIndex].mValue = aValue;
return NS_OK;
}
return NS_ERROR_ILLEGAL_VALUE;
void SetCounterResetAt(uint32_t aIndex, const nsString& aCounter, int32_t aValue) {
mResets[aIndex].mCounter = aCounter;
mResets[aIndex].mValue = aValue;
}
nsStyleCoord mMarkerOffset; // [reset] coord, auto
protected:
nsStyleContentData* mContents;
nsStyleCounterData* mIncrements;
nsStyleCounterData* mResets;
uint32_t mContentCount;
uint32_t mIncrementCount;
uint32_t mResetCount;
nsTArray<nsStyleContentData> mContents;
nsTArray<nsStyleCounterData> mIncrements;
nsTArray<nsStyleCounterData> mResets;
};
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset