Bug 1203766 - Part 6.1: Clear cached style context on nsComputedDOMStyle when its element is moved. r=bzbarsky

This commit is contained in:
Cameron McCormack 2015-09-17 12:08:21 +10:00
parent c6d52eae0d
commit ea96a6f45d
2 changed files with 70 additions and 12 deletions

View File

@ -264,9 +264,23 @@ nsComputedDOMStyle::nsComputedDOMStyle(dom::Element* aElement,
nsComputedDOMStyle::~nsComputedDOMStyle()
{
ClearStyleContext();
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsComputedDOMStyle, mContent)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsComputedDOMStyle)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsComputedDOMStyle)
tmp->ClearStyleContext(); // remove observer before clearing mContent
NS_IMPL_CYCLE_COLLECTION_UNLINK(mContent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsComputedDOMStyle)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContent)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsComputedDOMStyle)
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsComputedDOMStyle)
return tmp->IsBlack();
@ -283,6 +297,7 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
// QueryInterface implementation for nsComputedDOMStyle
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsComputedDOMStyle)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
NS_INTERFACE_MAP_END_INHERITING(nsDOMCSSDeclaration)
@ -571,13 +586,39 @@ nsComputedDOMStyle::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv
aCSSParseEnv.mPrincipal = nullptr;
}
void
nsComputedDOMStyle::ClearStyleContext()
{
if (mResolvedStyleContext) {
mResolvedStyleContext = false;
mContent->RemoveMutationObserver(this);
}
mStyleContext = nullptr;
}
void
nsComputedDOMStyle::SetResolvedStyleContext(nsRefPtr<nsStyleContext>&& aContext)
{
if (!mResolvedStyleContext) {
mResolvedStyleContext = true;
mContent->AddMutationObserver(this);
}
mStyleContext = aContext;
}
void
nsComputedDOMStyle::SetFrameStyleContext(nsStyleContext* aContext)
{
ClearStyleContext();
mStyleContext = aContext;
}
void
nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
{
nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocumentWeak);
if (!document) {
mResolvedStyleContext = false;
mStyleContext = nullptr;
ClearStyleContext();
return;
}
@ -595,8 +636,7 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
mPresShell = document->GetShell();
if (!mPresShell || !mPresShell->GetPresContext()) {
mResolvedStyleContext = false;
mStyleContext = nullptr;
ClearStyleContext();
return;
}
@ -632,8 +672,7 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
"the inner table");
}
mStyleContext = mInnerFrame->StyleContext();
mResolvedStyleContext = false;
SetFrameStyleContext(mInnerFrame->StyleContext());
NS_ASSERTION(mStyleContext, "Frame without style context?");
}
}
@ -661,13 +700,13 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
}
#endif
// Need to resolve a style context
mStyleContext =
nsRefPtr<nsStyleContext> resolvedStyleContext =
nsComputedDOMStyle::GetStyleContextForElement(mContent->AsElement(),
mPseudo,
mPresShell,
mStyleType);
if (!mStyleContext) {
mResolvedStyleContext = false;
if (!resolvedStyleContext) {
ClearStyleContext();
return;
}
@ -678,8 +717,7 @@ nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
mPresShell->GetPresContext()->GetRestyleGeneration(),
"why should we have flushed style again?");
mResolvedStyleContext = true;
mStyleContextGeneration = currentGeneration;
SetResolvedStyleContext(Move(resolvedStyleContext));
NS_ASSERTION(mPseudo || !mStyleContext->HasPseudoElementData(),
"should not have pseudo-element data");
}
@ -6018,6 +6056,17 @@ nsComputedDOMStyle::DoGetCustomProperty(const nsAString& aPropertyName)
return val;
}
void
nsComputedDOMStyle::ParentChainChanged(nsIContent* aContent)
{
NS_ASSERTION(mContent == aContent, "didn't we register mContent?");
NS_ASSERTION(mResolvedStyleContext,
"should have only registered an observer when "
"mResolvedStyleContext is true");
ClearStyleContext();
}
/* static */ nsComputedStyleMap*
nsComputedDOMStyle::GetComputedStyleMap()
{

View File

@ -45,6 +45,7 @@ class nsStyleSides;
struct nsTimingFunction;
class nsComputedDOMStyle final : public nsDOMCSSDeclaration
, public nsStubMutationObserver
{
public:
typedef nsCSSProps::KTableValue KTableValue;
@ -110,6 +111,9 @@ public:
static void RegisterPrefChangeCallbacks();
static void UnregisterPrefChangeCallbacks();
// nsIMutationObserver
NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
private:
virtual ~nsComputedDOMStyle();
@ -128,6 +132,11 @@ private:
void UpdateCurrentStyleSources(bool aNeedsLayoutFlush);
void ClearCurrentStyleSources();
// Helper functions called by UpdateCurrentStyleSources.
void ClearStyleContext();
void SetResolvedStyleContext(nsRefPtr<nsStyleContext>&& aContext);
void SetFrameStyleContext(nsStyleContext* aContext);
#define STYLE_STRUCT(name_, checkdata_cb_) \
const nsStyle##name_ * Style##name_() { \
return mStyleContext->Style##name_(); \