mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1363699 part 1 - Make named CounterStyle objects not refcounted. r=heycam
This change does the following: * Introduce a new smart pointer called CounterStylePtr which either holds an AnonymousCounterStyle strongly, or a named CounterStyle managed by CounterStyleManager weakly, and use it to replace all RefPtr<CounterStyle> around the codebase. * Rename CounterStyleManager::mCacheTable to mStyles to reflect the fact that it is used to manage all styles, not just for caching. * Add a retired styles list which collect all named CounterStyle evicted from mStyles, and post a PostRefreshObserver to destroy objects in that list after next flush. * Remove helper functions for counter style in nsStyleList and expose mCounterStyle directly, to make code simpler with the new pointer. Reason for adding a new smart pointer type rather than making their AddRef/Release behave like BuiltinCounterStyle is that, it is possible that after a flush, some stale style structs may still be alive. They can contain pointer to destroyed CounterStyle objects. Although the actual content may never be accessed anymore, RefPtr may still access the object for refcounting during destruction. MozReview-Commit-ID: xxegwSDhNb --HG-- extra : rebase_source : bb5443f0eb56eee51cbdfd08e0400335648610e8
This commit is contained in:
parent
a58b13f27d
commit
8c54e3ce73
@ -82,7 +82,7 @@ struct nsCounterUseNode : public nsCounterNode {
|
||||
RefPtr<nsCSSValue::Array> mCounterFunction;
|
||||
|
||||
nsPresContext* mPresContext;
|
||||
RefPtr<mozilla::CounterStyle> mCounterStyle;
|
||||
mozilla::CounterStylePtr mCounterStyle;
|
||||
|
||||
// false for counter(), true for counters()
|
||||
bool mAllCounters;
|
||||
@ -94,7 +94,6 @@ struct nsCounterUseNode : public nsCounterNode {
|
||||
: nsCounterNode(aContentIndex, USE)
|
||||
, mCounterFunction(aCounterFunction)
|
||||
, mPresContext(aPresContext)
|
||||
, mCounterStyle(nullptr)
|
||||
, mAllCounters(aAllCounters)
|
||||
{
|
||||
NS_ASSERTION(aContentIndex <= INT32_MAX, "out of range");
|
||||
|
@ -2282,6 +2282,29 @@ nsPresContext::UserFontSetUpdated(gfxUserFontEntry* aUpdatedFont)
|
||||
}
|
||||
}
|
||||
|
||||
class CounterStyleCleaner : public nsAPostRefreshObserver
|
||||
{
|
||||
public:
|
||||
CounterStyleCleaner(nsRefreshDriver* aRefreshDriver,
|
||||
CounterStyleManager* aCounterStyleManager)
|
||||
: mRefreshDriver(aRefreshDriver)
|
||||
, mCounterStyleManager(aCounterStyleManager)
|
||||
{
|
||||
}
|
||||
virtual ~CounterStyleCleaner() {}
|
||||
|
||||
void DidRefresh() final
|
||||
{
|
||||
mRefreshDriver->RemovePostRefreshObserver(this);
|
||||
mCounterStyleManager->CleanRetiredStyles();
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<nsRefreshDriver> mRefreshDriver;
|
||||
RefPtr<CounterStyleManager> mCounterStyleManager;
|
||||
};
|
||||
|
||||
void
|
||||
nsPresContext::FlushCounterStyles()
|
||||
{
|
||||
@ -2299,6 +2322,8 @@ nsPresContext::FlushCounterStyles()
|
||||
PresShell()->NotifyCounterStylesAreDirty();
|
||||
PostRebuildAllStyleDataEvent(NS_STYLE_HINT_REFLOW,
|
||||
eRestyle_ForceDescendants);
|
||||
RefreshDriver()->AddPostRefreshObserver(
|
||||
new CounterStyleCleaner(RefreshDriver(), mCounterStyleManager));
|
||||
}
|
||||
mCounterStylesDirty = false;
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ FontSizeInflationListMarginAdjustment(const nsIFrame* aFrame)
|
||||
blockFrame->HasBullet() &&
|
||||
inflation > 1.0f) {
|
||||
|
||||
auto listStyleType = aFrame->StyleList()->GetCounterStyle()->GetStyle();
|
||||
auto listStyleType = aFrame->StyleList()->mCounterStyle->GetStyle();
|
||||
if (listStyleType != NS_STYLE_LIST_STYLE_NONE &&
|
||||
listStyleType != NS_STYLE_LIST_STYLE_DISC &&
|
||||
listStyleType != NS_STYLE_LIST_STYLE_CIRCLE &&
|
||||
|
@ -7055,7 +7055,7 @@ nsBlockFrame::SetInitialChildList(ChildListID aListID,
|
||||
!GetPrevInFlow()) {
|
||||
// Resolve style for the bullet frame
|
||||
const nsStyleList* styleList = StyleList();
|
||||
CounterStyle* style = styleList->GetCounterStyle();
|
||||
CounterStyle* style = styleList->mCounterStyle;
|
||||
|
||||
CreateBulletFrameForListItem(
|
||||
style->IsBullet(),
|
||||
@ -7110,7 +7110,7 @@ nsBlockFrame::BulletIsEmpty() const
|
||||
mozilla::StyleDisplay::ListItem && HasOutsideBullet(),
|
||||
"should only care when we have an outside bullet");
|
||||
const nsStyleList* list = StyleList();
|
||||
return list->GetCounterStyle()->IsNone() &&
|
||||
return list->mCounterStyle->IsNone() &&
|
||||
!list->GetListStyleImage();
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ nsBulletFrame::IsEmpty()
|
||||
bool
|
||||
nsBulletFrame::IsSelfEmpty()
|
||||
{
|
||||
return StyleList()->GetCounterStyle()->IsNone();
|
||||
return StyleList()->mCounterStyle->IsNone();
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
@ -157,11 +157,11 @@ nsBulletFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||
const nsStyleList* oldStyleList = aOldStyleContext->PeekStyleList();
|
||||
if (oldStyleList) {
|
||||
bool hadBullet = oldStyleList->GetListStyleImage() ||
|
||||
!oldStyleList->GetCounterStyle()->IsNone();
|
||||
!oldStyleList->mCounterStyle->IsNone();
|
||||
|
||||
const nsStyleList* newStyleList = StyleList();
|
||||
bool hasBullet = newStyleList->GetListStyleImage() ||
|
||||
!newStyleList->GetCounterStyle()->IsNone();
|
||||
!newStyleList->mCounterStyle->IsNone();
|
||||
|
||||
if (hadBullet != hasBullet) {
|
||||
accService->UpdateListBullet(PresContext()->GetPresShell(), mContent,
|
||||
@ -696,7 +696,7 @@ Maybe<BulletRenderer>
|
||||
nsBulletFrame::CreateBulletRenderer(nsRenderingContext& aRenderingContext, nsPoint aPt)
|
||||
{
|
||||
const nsStyleList* myList = StyleList();
|
||||
CounterStyle* listStyleType = myList->GetCounterStyle();
|
||||
CounterStyle* listStyleType = myList->mCounterStyle;
|
||||
nsMargin padding = mPadding.GetPhysicalMargin(GetWritingMode());
|
||||
|
||||
if (myList->GetListStyleImage() && mImageRequest) {
|
||||
@ -904,7 +904,7 @@ nsBulletFrame::SetListItemOrdinal(int32_t aNextOrdinal,
|
||||
void
|
||||
nsBulletFrame::GetListItemText(nsAString& aResult)
|
||||
{
|
||||
CounterStyle* style = StyleList()->GetCounterStyle();
|
||||
CounterStyle* style = StyleList()->mCounterStyle;
|
||||
NS_ASSERTION(style->GetStyle() != NS_STYLE_LIST_STYLE_NONE &&
|
||||
style->GetStyle() != NS_STYLE_LIST_STYLE_DISC &&
|
||||
style->GetStyle() != NS_STYLE_LIST_STYLE_CIRCLE &&
|
||||
@ -991,7 +991,7 @@ nsBulletFrame::GetDesiredSize(nsPresContext* aCX,
|
||||
nscoord bulletSize;
|
||||
|
||||
nsAutoString text;
|
||||
switch (myList->GetCounterStyle()->GetStyle()) {
|
||||
switch (myList->mCounterStyle->GetStyle()) {
|
||||
case NS_STYLE_LIST_STYLE_NONE:
|
||||
finalSize.ISize(wm) = finalSize.BSize(wm) = 0;
|
||||
aMetrics.SetBlockStartAscent(0);
|
||||
@ -1113,7 +1113,7 @@ IsIgnoreable(const nsIFrame* aFrame, nscoord aISize)
|
||||
return false;
|
||||
}
|
||||
auto listStyle = aFrame->StyleList();
|
||||
return listStyle->GetCounterStyle()->IsNone() &&
|
||||
return listStyle->mCounterStyle->IsNone() &&
|
||||
!listStyle->GetListStyleImage();
|
||||
}
|
||||
|
||||
@ -1350,7 +1350,7 @@ nsBulletFrame::GetLogicalBaseline(WritingMode aWritingMode) const
|
||||
} else {
|
||||
RefPtr<nsFontMetrics> fm =
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, GetFontSizeInflation());
|
||||
CounterStyle* listStyleType = StyleList()->GetCounterStyle();
|
||||
CounterStyle* listStyleType = StyleList()->mCounterStyle;
|
||||
switch (listStyleType->GetStyle()) {
|
||||
case NS_STYLE_LIST_STYLE_NONE:
|
||||
break;
|
||||
@ -1387,7 +1387,7 @@ nsBulletFrame::GetLogicalBaseline(WritingMode aWritingMode) const
|
||||
void
|
||||
nsBulletFrame::GetSpokenText(nsAString& aText)
|
||||
{
|
||||
CounterStyle* style = StyleList()->GetCounterStyle();
|
||||
CounterStyle* style = StyleList()->mCounterStyle;
|
||||
bool isBullet;
|
||||
style->GetSpokenCounterText(mOrdinal, GetWritingMode(), aText, isBullet);
|
||||
if (isBullet) {
|
||||
|
@ -611,10 +611,6 @@ public:
|
||||
WritingMode aWritingMode,
|
||||
nsSubstring& aResult,
|
||||
bool& aIsRTL) override;
|
||||
|
||||
// Builtin counter style does not need refcount at all
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef() override { return 2; }
|
||||
NS_IMETHOD_(MozExternalRefCountType) Release() override { return 2; }
|
||||
};
|
||||
|
||||
/* virtual */ void
|
||||
@ -962,8 +958,6 @@ BuiltinCounterStyle::GetInitialCounterText(CounterValue aOrdinal,
|
||||
|
||||
class DependentBuiltinCounterStyle final : public BuiltinCounterStyle
|
||||
{
|
||||
private:
|
||||
~DependentBuiltinCounterStyle() {}
|
||||
public:
|
||||
DependentBuiltinCounterStyle(int32_t aStyle, CounterStyleManager* aManager)
|
||||
: BuiltinCounterStyle(aStyle),
|
||||
@ -975,18 +969,12 @@ public:
|
||||
|
||||
virtual CounterStyle* GetFallback() override;
|
||||
|
||||
// DependentBuiltinCounterStyle is managed in the same way as
|
||||
// CustomCounterStyle.
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef() override;
|
||||
NS_IMETHOD_(MozExternalRefCountType) Release() override;
|
||||
|
||||
void* operator new(size_t sz, nsPresContext* aPresContext)
|
||||
{
|
||||
return aPresContext->PresShell()->AllocateByObjectID(
|
||||
eArenaObjectID_DependentBuiltinCounterStyle, sz);
|
||||
}
|
||||
|
||||
private:
|
||||
void Destroy()
|
||||
{
|
||||
nsIPresShell* shell = mManager->PresContext()->PresShell();
|
||||
@ -994,15 +982,12 @@ private:
|
||||
shell->FreeByObjectID(eArenaObjectID_DependentBuiltinCounterStyle, this);
|
||||
}
|
||||
|
||||
private:
|
||||
~DependentBuiltinCounterStyle() {}
|
||||
|
||||
CounterStyleManager* mManager;
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(DependentBuiltinCounterStyle)
|
||||
NS_IMPL_RELEASE_WITH_DESTROY(DependentBuiltinCounterStyle, Destroy())
|
||||
|
||||
/* virtual */ CounterStyle*
|
||||
DependentBuiltinCounterStyle::GetFallback()
|
||||
{
|
||||
@ -1029,8 +1014,6 @@ DependentBuiltinCounterStyle::GetFallback()
|
||||
|
||||
class CustomCounterStyle final : public CounterStyle
|
||||
{
|
||||
private:
|
||||
~CustomCounterStyle() {}
|
||||
public:
|
||||
CustomCounterStyle(nsIAtom* aName,
|
||||
CounterStyleManager* aManager,
|
||||
@ -1095,19 +1078,12 @@ public:
|
||||
return mSystem == NS_STYLE_COUNTER_SYSTEM_EXTENDS;
|
||||
}
|
||||
|
||||
// CustomCounterStyle should be reference-counted because it may be
|
||||
// dereferenced from the manager but still referenced by nodes and
|
||||
// frames before the style change is propagated.
|
||||
NS_IMETHOD_(MozExternalRefCountType) AddRef() override;
|
||||
NS_IMETHOD_(MozExternalRefCountType) Release() override;
|
||||
|
||||
void* operator new(size_t sz, nsPresContext* aPresContext)
|
||||
{
|
||||
return aPresContext->PresShell()->AllocateByObjectID(
|
||||
eArenaObjectID_CustomCounterStyle, sz);
|
||||
}
|
||||
|
||||
private:
|
||||
void Destroy()
|
||||
{
|
||||
nsIPresShell* shell = mManager->PresContext()->PresShell();
|
||||
@ -1115,6 +1091,9 @@ private:
|
||||
shell->FreeByObjectID(eArenaObjectID_CustomCounterStyle, this);
|
||||
}
|
||||
|
||||
private:
|
||||
~CustomCounterStyle() {}
|
||||
|
||||
const nsTArray<nsString>& GetSymbols();
|
||||
const nsTArray<AdditiveSymbol>& GetAdditiveSymbols();
|
||||
|
||||
@ -1190,14 +1169,8 @@ private:
|
||||
// counter must be either a builtin style or a style whose system is
|
||||
// not 'extends'.
|
||||
CounterStyle* mExtendsRoot;
|
||||
|
||||
nsAutoRefCnt mRefCnt;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(CustomCounterStyle)
|
||||
NS_IMPL_RELEASE_WITH_DESTROY(CustomCounterStyle, Destroy())
|
||||
|
||||
void
|
||||
CustomCounterStyle::ResetCachedData()
|
||||
{
|
||||
@ -1987,8 +1960,8 @@ CounterStyleManager::CounterStyleManager(nsPresContext* aPresContext)
|
||||
: mPresContext(aPresContext)
|
||||
{
|
||||
// Insert the static styles into cache table
|
||||
mCacheTable.Put(nsGkAtoms::none, GetNoneStyle());
|
||||
mCacheTable.Put(nsGkAtoms::decimal, GetDecimalStyle());
|
||||
mStyles.Put(nsGkAtoms::none, GetNoneStyle());
|
||||
mStyles.Put(nsGkAtoms::decimal, GetDecimalStyle());
|
||||
}
|
||||
|
||||
CounterStyleManager::~CounterStyleManager()
|
||||
@ -2004,26 +1977,38 @@ CounterStyleManager::InitializeBuiltinCounterStyles()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CounterStyleManager::DestroyCounterStyle(CounterStyle* aCounterStyle)
|
||||
{
|
||||
if (aCounterStyle->IsCustomStyle()) {
|
||||
MOZ_ASSERT(!aCounterStyle->AsAnonymous(), "Anonymous counter styles "
|
||||
"are not managed by CounterStyleManager");
|
||||
static_cast<CustomCounterStyle*>(aCounterStyle)->Destroy();
|
||||
} else if (aCounterStyle->IsDependentStyle()) {
|
||||
static_cast<DependentBuiltinCounterStyle*>(aCounterStyle)->Destroy();
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("Builtin counter styles should not be destroyed");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CounterStyleManager::Disconnect()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
for (auto iter = mCacheTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
CounterStyle* style = iter.UserData();
|
||||
style->AddRef();
|
||||
auto refcnt = style->Release();
|
||||
NS_ASSERTION(!style->IsDependentStyle() || refcnt == 1,
|
||||
"Counter style is still referenced by other objects.");
|
||||
CleanRetiredStyles();
|
||||
for (auto iter = mStyles.Iter(); !iter.Done(); iter.Next()) {
|
||||
CounterStyle* style = iter.Data();
|
||||
if (style->IsDependentStyle()) {
|
||||
DestroyCounterStyle(style);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
mCacheTable.Clear();
|
||||
mStyles.Clear();
|
||||
mPresContext = nullptr;
|
||||
}
|
||||
|
||||
CounterStyle*
|
||||
CounterStyleManager::BuildCounterStyle(nsIAtom* aName)
|
||||
{
|
||||
CounterStyle* data = mCacheTable.GetWeak(aName);
|
||||
CounterStyle* data = mStyles.Get(aName);
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
@ -2058,7 +2043,7 @@ CounterStyleManager::BuildCounterStyle(nsIAtom* aName)
|
||||
if (!data) {
|
||||
data = GetDecimalStyle();
|
||||
}
|
||||
mCacheTable.Put(aName, data);
|
||||
mStyles.Put(aName, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -2076,9 +2061,8 @@ bool
|
||||
CounterStyleManager::NotifyRuleChanged()
|
||||
{
|
||||
bool changed = false;
|
||||
nsTArray<RefPtr<CounterStyle>> kungFuDeathGrip;
|
||||
for (auto iter = mCacheTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
RefPtr<CounterStyle>& style = iter.Data();
|
||||
for (auto iter = mStyles.Iter(); !iter.Done(); iter.Next()) {
|
||||
CounterStyle* style = iter.Data();
|
||||
bool toBeUpdated = false;
|
||||
bool toBeRemoved = false;
|
||||
// XXXheycam ServoStyleSets do not support custom counter styles yet. Bug
|
||||
@ -2099,7 +2083,7 @@ CounterStyleManager::NotifyRuleChanged()
|
||||
if (!style->IsCustomStyle()) {
|
||||
toBeRemoved = true;
|
||||
} else {
|
||||
auto custom = static_cast<CustomCounterStyle*>(style.get());
|
||||
auto custom = static_cast<CustomCounterStyle*>(style);
|
||||
if (custom->GetRule() != newRule) {
|
||||
toBeRemoved = true;
|
||||
} else if (custom->GetRuleGeneration() != newRule->GetGeneration()) {
|
||||
@ -2111,25 +2095,16 @@ CounterStyleManager::NotifyRuleChanged()
|
||||
changed = changed || toBeUpdated || toBeRemoved;
|
||||
if (toBeRemoved) {
|
||||
if (style->IsDependentStyle()) {
|
||||
if (style->IsCustomStyle()) {
|
||||
// Since |style| is being removed from mCacheTable, it won't be
|
||||
// visited by our post-removal iteration. So, we have to give it a
|
||||
// manual ResetDependentData() call. (This only really matters if
|
||||
// something else is holding a reference and keeping it alive.)
|
||||
static_cast<CustomCounterStyle*>(style.get())->ResetDependentData();
|
||||
}
|
||||
// The object has to be held here so that it will not be released
|
||||
// before all pointers that refer to it are reset. It will be released
|
||||
// when kungFuDeathGrip goes out of scope at the end of this function.
|
||||
kungFuDeathGrip.AppendElement(style);
|
||||
// Add object to retired list so we can clean them up later.
|
||||
mRetiredStyles.AppendElement(style);
|
||||
}
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
for (auto iter = mCacheTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
CounterStyle* style = iter.UserData();
|
||||
for (auto iter = mStyles.Iter(); !iter.Done(); iter.Next()) {
|
||||
CounterStyle* style = iter.Data();
|
||||
if (style->IsCustomStyle()) {
|
||||
CustomCounterStyle* custom = static_cast<CustomCounterStyle*>(style);
|
||||
custom->ResetDependentData();
|
||||
@ -2141,4 +2116,13 @@ CounterStyleManager::NotifyRuleChanged()
|
||||
return changed;
|
||||
}
|
||||
|
||||
void
|
||||
CounterStyleManager::CleanRetiredStyles()
|
||||
{
|
||||
nsTArray<CounterStyle*> list(Move(mRetiredStyles));
|
||||
for (CounterStyle* style : list) {
|
||||
DestroyCounterStyle(style);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -7,7 +7,7 @@
|
||||
#define mozilla_CounterStyleManager_h_
|
||||
|
||||
#include "nsStringFwd.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#include "nsStyleConsts.h"
|
||||
@ -96,8 +96,6 @@ public:
|
||||
|
||||
virtual AnonymousCounterStyle* AsAnonymous() { return nullptr; }
|
||||
|
||||
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
|
||||
|
||||
protected:
|
||||
int32_t mStyle;
|
||||
};
|
||||
@ -132,7 +130,7 @@ public:
|
||||
uint8_t GetSystem() const { return mSystem; }
|
||||
const nsTArray<nsString>& GetSymbols() const { return mSymbols; }
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(AnonymousCounterStyle, override)
|
||||
NS_INLINE_DECL_REFCOUNTING(AnonymousCounterStyle)
|
||||
|
||||
private:
|
||||
~AnonymousCounterStyle() {}
|
||||
@ -142,6 +140,105 @@ private:
|
||||
nsTArray<nsString> mSymbols;
|
||||
};
|
||||
|
||||
// A smart pointer to CounterStyle. It either owns a reference to an
|
||||
// anonymous counter style, or weakly refers to a named counter style
|
||||
// managed by counter style manager.
|
||||
class CounterStylePtr
|
||||
{
|
||||
public:
|
||||
CounterStylePtr() : mRaw(0) {}
|
||||
CounterStylePtr(const CounterStylePtr& aOther)
|
||||
: mRaw(aOther.mRaw)
|
||||
{
|
||||
if (IsAnonymous()) {
|
||||
AsAnonymous()->AddRef();
|
||||
}
|
||||
}
|
||||
~CounterStylePtr() { Reset(); }
|
||||
|
||||
CounterStylePtr& operator=(const CounterStylePtr& aOther)
|
||||
{
|
||||
if (this != &aOther) {
|
||||
Reset();
|
||||
new (this) CounterStylePtr(aOther);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
CounterStylePtr& operator=(decltype(nullptr))
|
||||
{
|
||||
Reset();
|
||||
return *this;
|
||||
}
|
||||
CounterStylePtr& operator=(AnonymousCounterStyle* aCounterStyle)
|
||||
{
|
||||
Reset();
|
||||
if (aCounterStyle) {
|
||||
CounterStyle* raw = do_AddRef(aCounterStyle).take();
|
||||
AssertPointerAligned(raw);
|
||||
mRaw = reinterpret_cast<uintptr_t>(raw) | kAnonymousFlag;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
CounterStylePtr& operator=(CounterStyle* aCounterStyle)
|
||||
{
|
||||
Reset();
|
||||
if (aCounterStyle) {
|
||||
MOZ_ASSERT(!aCounterStyle->AsAnonymous());
|
||||
AssertPointerAligned(aCounterStyle);
|
||||
mRaw = reinterpret_cast<uintptr_t>(aCounterStyle);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator CounterStyle*() const & { return Get(); }
|
||||
operator CounterStyle*() const && = delete;
|
||||
CounterStyle* operator->() const { return Get(); }
|
||||
explicit operator bool() const { return !!mRaw; }
|
||||
bool operator!() const { return !mRaw; }
|
||||
bool operator==(const CounterStylePtr& aOther) const
|
||||
{ return mRaw == aOther.mRaw; }
|
||||
bool operator!=(const CounterStylePtr& aOther) const
|
||||
{ return mRaw != aOther.mRaw; }
|
||||
|
||||
private:
|
||||
CounterStyle* Get() const
|
||||
{
|
||||
return reinterpret_cast<CounterStyle*>(mRaw & ~kAnonymousFlag);
|
||||
}
|
||||
void AssertPointerAligned(CounterStyle* aPointer)
|
||||
{
|
||||
// This can be checked at compile time via
|
||||
// > static_assert(alignof(CounterStyle) >= 2);
|
||||
// but MSVC2015 doesn't support using alignof on an abstract class.
|
||||
// Once we move to MSVC2017, we can replace this runtime check with
|
||||
// the compile time check above.
|
||||
MOZ_ASSERT(!(reinterpret_cast<uintptr_t>(aPointer) & kAnonymousFlag));
|
||||
}
|
||||
|
||||
bool IsAnonymous() const { return !!(mRaw & kAnonymousFlag); }
|
||||
AnonymousCounterStyle* AsAnonymous()
|
||||
{
|
||||
MOZ_ASSERT(IsAnonymous());
|
||||
return static_cast<AnonymousCounterStyle*>(
|
||||
reinterpret_cast<CounterStyle*>(mRaw & ~kAnonymousFlag));
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (IsAnonymous()) {
|
||||
AsAnonymous()->Release();
|
||||
}
|
||||
mRaw = 0;
|
||||
}
|
||||
|
||||
// mRaw contains the pointer, and its last bit is used for the flag.
|
||||
// If the flag is set, this pointer owns an AnonymousCounterStyle,
|
||||
// otherwise, it is a weak pointer referring a named counter style
|
||||
// managed by CounterStyleManager.
|
||||
static const uintptr_t kAnonymousFlag = 1;
|
||||
uintptr_t mRaw;
|
||||
};
|
||||
|
||||
class CounterStyleManager final
|
||||
{
|
||||
private:
|
||||
@ -156,7 +253,7 @@ public:
|
||||
bool IsInitial() const
|
||||
{
|
||||
// only 'none' and 'decimal'
|
||||
return mCacheTable.Count() == 2;
|
||||
return mStyles.Count() == 2;
|
||||
}
|
||||
|
||||
CounterStyle* BuildCounterStyle(nsIAtom* aName);
|
||||
@ -176,14 +273,21 @@ public:
|
||||
// if any counter style is changed, false elsewise. This method should
|
||||
// be called when any counter style may be affected.
|
||||
bool NotifyRuleChanged();
|
||||
// NotifyRuleChanged will evict no longer needed counter styles into
|
||||
// mRetiredStyles, and this function destroys all objects listed there.
|
||||
// It should be called only after no one may ever use those objects.
|
||||
void CleanRetiredStyles();
|
||||
|
||||
nsPresContext* PresContext() const { return mPresContext; }
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(CounterStyleManager)
|
||||
|
||||
private:
|
||||
void DestroyCounterStyle(CounterStyle* aCounterStyle);
|
||||
|
||||
nsPresContext* mPresContext;
|
||||
nsRefPtrHashtable<nsRefPtrHashKey<nsIAtom>, CounterStyle> mCacheTable;
|
||||
nsDataHashtable<nsRefPtrHashKey<nsIAtom>, CounterStyle*> mStyles;
|
||||
nsTArray<CounterStyle*> mRetiredStyles;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -1112,17 +1112,15 @@ Gecko_CopyImageOrientationFrom(nsStyleVisibility* aDst,
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_SetListStyleType(nsStyleList* style_struct, uint32_t type)
|
||||
Gecko_SetListStyleType(nsStyleList* aList, uint32_t aType)
|
||||
{
|
||||
// Builtin counter styles are static and use no-op refcounting, and thus are
|
||||
// safe to use off-main-thread.
|
||||
style_struct->SetCounterStyle(CounterStyleManager::GetBuiltinStyle(type));
|
||||
aList->mCounterStyle = CounterStyleManager::GetBuiltinStyle(aType);
|
||||
}
|
||||
|
||||
void
|
||||
Gecko_CopyListStyleTypeFrom(nsStyleList* dst, const nsStyleList* src)
|
||||
Gecko_CopyListStyleTypeFrom(nsStyleList* aDst, const nsStyleList* aSrc)
|
||||
{
|
||||
dst->SetCounterStyle(src->GetCounterStyle());
|
||||
aDst->mCounterStyle = aSrc->mCounterStyle;
|
||||
}
|
||||
|
||||
already_AddRefed<css::URLValue>
|
||||
|
@ -3714,13 +3714,13 @@ already_AddRefed<CSSValue>
|
||||
nsComputedDOMStyle::DoGetListStyleType()
|
||||
{
|
||||
RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
|
||||
CounterStyle* style = StyleList()->GetCounterStyle();
|
||||
CounterStyle* style = StyleList()->mCounterStyle;
|
||||
AnonymousCounterStyle* anonymous = style->AsAnonymous();
|
||||
nsAutoString tmp;
|
||||
if (!anonymous) {
|
||||
// want SetIdent
|
||||
nsString type;
|
||||
StyleList()->GetListStyleType(type);
|
||||
style->GetStyleName(type);
|
||||
nsStyleUtil::AppendEscapedCSSIdent(type, tmp);
|
||||
} else if (anonymous->IsSingleString()) {
|
||||
const nsTArray<nsString>& symbols = anonymous->GetSymbols();
|
||||
|
@ -7954,24 +7954,28 @@ nsRuleNode::ComputeListData(void* aStartStruct,
|
||||
|
||||
// list-style-type: string, none, inherit, initial
|
||||
const nsCSSValue* typeValue = aRuleData->ValueForListStyleType();
|
||||
auto setListStyleType = [this, list](nsIAtom* type) {
|
||||
list->mCounterStyle = mPresContext->
|
||||
CounterStyleManager()->BuildCounterStyle(type);
|
||||
};
|
||||
switch (typeValue->GetUnit()) {
|
||||
case eCSSUnit_Unset:
|
||||
case eCSSUnit_Inherit: {
|
||||
conditions.SetUncacheable();
|
||||
list->SetCounterStyle(parentList->GetCounterStyle());
|
||||
list->mCounterStyle = parentList->mCounterStyle;
|
||||
break;
|
||||
}
|
||||
case eCSSUnit_Initial:
|
||||
list->SetListStyleType(nsGkAtoms::disc, mPresContext);
|
||||
setListStyleType(nsGkAtoms::disc);
|
||||
break;
|
||||
case eCSSUnit_AtomIdent: {
|
||||
list->SetListStyleType(typeValue->GetAtomValue(), mPresContext);
|
||||
setListStyleType(typeValue->GetAtomValue());
|
||||
break;
|
||||
}
|
||||
case eCSSUnit_String: {
|
||||
nsString str;
|
||||
typeValue->GetStringValue(str);
|
||||
list->SetCounterStyle(new AnonymousCounterStyle(str));
|
||||
list->mCounterStyle = new AnonymousCounterStyle(str);
|
||||
break;
|
||||
}
|
||||
case eCSSUnit_Enumerated: {
|
||||
@ -7997,11 +8001,12 @@ nsRuleNode::ComputeListData(void* aStartStruct,
|
||||
intValue, nsCSSProps::kListStyleKTable));
|
||||
break;
|
||||
}
|
||||
list->SetListStyleType(name, mPresContext);
|
||||
setListStyleType(name);
|
||||
break;
|
||||
}
|
||||
case eCSSUnit_Symbols:
|
||||
list->SetCounterStyle(new AnonymousCounterStyle(typeValue->GetArrayValue()));
|
||||
list->mCounterStyle =
|
||||
new AnonymousCounterStyle(typeValue->GetArrayValue());
|
||||
break;
|
||||
case eCSSUnit_Null:
|
||||
break;
|
||||
|
@ -1476,23 +1476,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList
|
||||
|
||||
already_AddRefed<nsIURI> GetListStyleImageURI() const;
|
||||
|
||||
void GetListStyleType(nsSubstring& aType) const { mCounterStyle->GetStyleName(aType); }
|
||||
mozilla::CounterStyle* GetCounterStyle() const
|
||||
{
|
||||
return mCounterStyle.get();
|
||||
}
|
||||
void SetCounterStyle(mozilla::CounterStyle* aStyle)
|
||||
{
|
||||
// NB: This function is called off-main-thread during parallel restyle, but
|
||||
// only with builtin styles that use dummy refcounting.
|
||||
MOZ_ASSERT(NS_IsMainThread() || !aStyle->IsDependentStyle());
|
||||
mCounterStyle = aStyle;
|
||||
}
|
||||
void SetListStyleType(nsIAtom* aType, nsPresContext* aPresContext)
|
||||
{
|
||||
SetCounterStyle(aPresContext->CounterStyleManager()->BuildCounterStyle(aType));
|
||||
}
|
||||
|
||||
const nsStyleQuoteValues::QuotePairArray& GetQuotePairs() const;
|
||||
|
||||
void SetQuotesInherit(const nsStyleList* aOther);
|
||||
@ -1502,8 +1485,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList
|
||||
|
||||
uint8_t mListStylePosition; // [inherited]
|
||||
RefPtr<nsStyleImageRequest> mListStyleImage; // [inherited]
|
||||
mozilla::CounterStylePtr mCounterStyle; // [inherited]
|
||||
private:
|
||||
RefPtr<mozilla::CounterStyle> mCounterStyle; // [inherited]
|
||||
RefPtr<nsStyleQuoteValues> mQuotes; // [inherited]
|
||||
nsStyleList& operator=(const nsStyleList& aOther) = delete;
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user