Fix for 99344, inline styles not being recognized under certain DHTML circumstances. r=dbaron, sr=waterson, a=asa
git-svn-id: svn://10.0.0.236/trunk@118229 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -59,6 +59,7 @@
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsIDOMHTMLBodyElement.h"
|
||||
#include "nsHTMLAtoms.h"
|
||||
#include "nsHashtable.h"
|
||||
|
||||
#ifdef MOZ_PERF_METRICS
|
||||
#include "nsITimeRecorder.h"
|
||||
@@ -73,6 +74,34 @@
|
||||
|
||||
#include "nsISizeOfHandler.h"
|
||||
|
||||
// =====================================================
|
||||
// nsRuleNodeList
|
||||
// A class that represents a chain of rule nodes
|
||||
|
||||
struct nsRuleNodeList
|
||||
{
|
||||
nsRuleNodeList(nsRuleNode* aRuleNode, nsRuleNodeList* aNext = nsnull)
|
||||
:mRuleNode(aRuleNode), mNext(aNext)
|
||||
{};
|
||||
|
||||
void* operator new(size_t sz, nsIPresContext* aContext) {
|
||||
void* result = nsnull;
|
||||
aContext->AllocateFromShell(sz, &result);
|
||||
return result;
|
||||
};
|
||||
|
||||
void Destroy() {
|
||||
if (mNext)
|
||||
mNext->Destroy();
|
||||
mRuleNode->PresContext()->FreeToShell(sizeof(nsRuleNodeList), this);
|
||||
};
|
||||
|
||||
nsRuleNode* mRuleNode;
|
||||
nsRuleNodeList* mNext;
|
||||
};
|
||||
|
||||
// =====================================================
|
||||
|
||||
static NS_DEFINE_IID(kIStyleFrameConstructionIID, NS_ISTYLE_FRAME_CONSTRUCTION_IID);
|
||||
|
||||
class StyleSetImpl : public nsIStyleSet
|
||||
@@ -160,6 +189,8 @@ public:
|
||||
|
||||
virtual nsresult GetRuleTree(nsRuleNode** aResult);
|
||||
virtual nsresult ClearCachedDataInRuleTree(nsIStyleRule* aRule);
|
||||
|
||||
virtual nsresult AddRuleNodeMapping(nsRuleNode* aRuleNode);
|
||||
|
||||
virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsIStyleContext* aContext);
|
||||
|
||||
@@ -336,6 +367,7 @@ protected:
|
||||
nsRuleNode* mOldRuleTree; // Used during rule tree reconstruction.
|
||||
nsRuleWalker* mRuleWalker; // This is an instance of a rule walker that can be used
|
||||
// to navigate through our tree.
|
||||
nsHashtable mRuleMappings; // A hashtable from rules to rule node lists.
|
||||
|
||||
MOZ_TIMER_DECLARE(mStyleResolutionWatch)
|
||||
|
||||
@@ -353,7 +385,8 @@ StyleSetImpl::StyleSetImpl()
|
||||
mQuirkStyleSheet(nsnull),
|
||||
mRuleTree(nsnull),
|
||||
mOldRuleTree(nsnull),
|
||||
mRuleWalker(nsnull)
|
||||
mRuleWalker(nsnull),
|
||||
mRuleMappings(32)
|
||||
#ifdef MOZ_PERF_METRICS
|
||||
,mTimerEnabled(PR_FALSE)
|
||||
#endif
|
||||
@@ -1218,9 +1251,19 @@ nsIStyleContext* StyleSetImpl::ProbePseudoStyleFor(nsIPresContext* aPresContext,
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool PR_CALLBACK DeleteRuleNodeLists(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
{
|
||||
nsRuleNodeList* ruleNodeList = (nsRuleNodeList*)aData;
|
||||
ruleNodeList->Destroy();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
StyleSetImpl::Shutdown()
|
||||
{
|
||||
mRuleMappings.Enumerate(DeleteRuleNodeLists);
|
||||
mRuleMappings.Reset();
|
||||
|
||||
delete mRuleWalker;
|
||||
if (mRuleTree)
|
||||
{
|
||||
@@ -1237,6 +1280,17 @@ StyleSetImpl::GetRuleTree(nsRuleNode** aResult)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
StyleSetImpl::AddRuleNodeMapping(nsRuleNode* aRuleNode)
|
||||
{
|
||||
nsVoidKey key(aRuleNode->Rule());
|
||||
nsRuleNodeList* ruleList =
|
||||
new (aRuleNode->PresContext()) nsRuleNodeList(aRuleNode,
|
||||
NS_STATIC_CAST(nsRuleNodeList*, mRuleMappings.Get(&key)));
|
||||
mRuleMappings.Put(&key, ruleList);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
StyleSetImpl::BeginRuleTreeReconstruct()
|
||||
{
|
||||
@@ -1244,6 +1298,8 @@ StyleSetImpl::BeginRuleTreeReconstruct()
|
||||
mRuleWalker = nsnull;
|
||||
mOldRuleTree = mRuleTree;
|
||||
mRuleTree = nsnull;
|
||||
mRuleMappings.Enumerate(DeleteRuleNodeLists);
|
||||
mRuleMappings.Reset();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -1274,6 +1330,20 @@ StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule,
|
||||
// style.left, we really only need to blow away cached
|
||||
// data in the position struct.
|
||||
if (aContext) {
|
||||
// |aRule| should never be null, but we'll sanity check it just in case.
|
||||
if (aRule) {
|
||||
// Obtain our rule node list and clear out the cached data in all rule nodes
|
||||
// that correspond to this rule. See bug 99344 for more details as to how
|
||||
// inline style rules can end up with multiple rule nodes in a rule tree.
|
||||
nsVoidKey key(aRule);
|
||||
nsRuleNodeList* ruleList = NS_STATIC_CAST(nsRuleNodeList*, mRuleMappings.Get(&key));
|
||||
for ( ; ruleList; ruleList = ruleList->mNext)
|
||||
ruleList->mRuleNode->ClearCachedData(aRule);
|
||||
}
|
||||
|
||||
// XXXdwh I'm just being paranoid here. Also clear out the data starting at the style
|
||||
// context's rule node. This really should always be done in the for loop above,
|
||||
// but I'm going to leave this here just in case (for now).
|
||||
nsRuleNode* ruleNode;
|
||||
aContext->GetRuleNode(&ruleNode);
|
||||
ruleNode->ClearCachedData(aRule);
|
||||
|
||||
Reference in New Issue
Block a user