From 906d582953d69e77df61e010f36e516442652419 Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Wed, 18 Jun 2003 01:59:57 +0000 Subject: [PATCH] Make CSSStyleRuleImpl immutable by changing mutation code (including some merging of code between nsDOMCSSAttributeDeclaration and DOMCSSDeclarationImpl) so that it creates a new rule for the modified declaration. Change StyleRuleChanged notification signatures, and change pres shell's handling of style rule change, addition, and removal to just do reresolution. Remove fine-grained ways of clearing style data. Change PeekStyleData so it doesn't do more work than it needs to, and can be relied on not to access rules that no longer match any content. b=188803 r+sr=bzbarsky git-svn-id: svn://10.0.0.236/trunk@143831 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/public/nsIDocument.h | 4 +- .../content/base/public/nsIDocumentObserver.h | 29 +- mozilla/content/base/public/nsIStyleRule.h | 43 ++- mozilla/content/base/src/nsDocument.cpp | 5 +- mozilla/content/base/src/nsDocument.h | 8 +- mozilla/content/base/src/nsRuleNode.cpp | 167 ++++----- mozilla/content/base/src/nsStyleContext.cpp | 21 +- mozilla/content/base/src/nsStyleSet.cpp | 70 +--- .../html/document/src/nsHTMLContentSink.cpp | 3 +- .../html/style/public/nsICSSStyleSheet.h | 2 + .../content/html/style/src/nsCSSParser.cpp | 6 +- mozilla/content/html/style/src/nsCSSRules.cpp | 15 + .../content/html/style/src/nsCSSStyleRule.cpp | 323 +++++++----------- .../html/style/src/nsCSSStyleSheet.cpp | 54 ++- .../style/src/nsDOMCSSAttrDeclaration.cpp | 158 ++------- .../html/style/src/nsDOMCSSAttrDeclaration.h | 14 +- .../html/style/src/nsDOMCSSDeclaration.cpp | 129 ++++++- .../html/style/src/nsDOMCSSDeclaration.h | 42 +-- .../content/html/style/src/nsICSSGroupRule.h | 9 +- .../content/html/style/src/nsICSSStyleRule.h | 16 +- mozilla/content/shared/public/nsRuleNode.h | 50 ++- .../content/shared/public/nsStyleContext.h | 2 +- mozilla/layout/base/nsCSSFrameConstructor.cpp | 72 ---- mozilla/layout/base/nsCSSFrameConstructor.h | 14 - mozilla/layout/base/nsPresContext.cpp | 2 +- mozilla/layout/base/nsPresShell.cpp | 36 +- .../base/public/nsIStyleFrameConstruction.h | 55 --- mozilla/layout/base/public/nsIStyleSet.h | 21 +- mozilla/layout/base/src/nsPresContext.cpp | 2 +- mozilla/layout/html/base/src/nsPresShell.cpp | 36 +- .../html/style/src/nsCSSFrameConstructor.cpp | 72 ---- .../html/style/src/nsCSSFrameConstructor.h | 14 - mozilla/layout/style/nsCSSParser.cpp | 6 +- mozilla/layout/style/nsCSSRules.cpp | 15 + mozilla/layout/style/nsCSSStyleRule.cpp | 323 +++++++----------- mozilla/layout/style/nsCSSStyleSheet.cpp | 54 ++- .../layout/style/nsDOMCSSAttrDeclaration.cpp | 158 ++------- .../layout/style/nsDOMCSSAttrDeclaration.h | 14 +- mozilla/layout/style/nsDOMCSSDeclaration.cpp | 129 ++++++- mozilla/layout/style/nsDOMCSSDeclaration.h | 42 +-- mozilla/layout/style/nsICSSGroupRule.h | 9 +- mozilla/layout/style/nsICSSStyleRule.h | 16 +- mozilla/layout/style/nsICSSStyleSheet.h | 2 + mozilla/layout/style/nsIStyleRule.h | 43 ++- mozilla/layout/style/nsRuleNode.cpp | 167 ++++----- mozilla/layout/style/nsRuleNode.h | 50 ++- mozilla/layout/style/nsStyleContext.cpp | 21 +- mozilla/layout/style/nsStyleContext.h | 2 +- mozilla/layout/style/nsStyleSet.cpp | 70 +--- 49 files changed, 1063 insertions(+), 1552 deletions(-) diff --git a/mozilla/content/base/public/nsIDocument.h b/mozilla/content/base/public/nsIDocument.h index 29b3d4f0a99..195491dd9f7 100644 --- a/mozilla/content/base/public/nsIDocument.h +++ b/mozilla/content/base/public/nsIDocument.h @@ -417,8 +417,8 @@ public: // Observation hooks for style data to propagate notifications // to document observers NS_IMETHOD StyleRuleChanged(nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) = 0; + nsIStyleRule* aOldStyleRule, + nsIStyleRule* aNewStyleRule) = 0; NS_IMETHOD StyleRuleAdded(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) = 0; NS_IMETHOD StyleRuleRemoved(nsIStyleSheet* aStyleSheet, diff --git a/mozilla/content/base/public/nsIDocumentObserver.h b/mozilla/content/base/public/nsIDocumentObserver.h index 5f9e71a86ca..fcb29b9bd97 100644 --- a/mozilla/content/base/public/nsIDocumentObserver.h +++ b/mozilla/content/base/public/nsIDocumentObserver.h @@ -281,15 +281,26 @@ public: * the document. The notification is passed on to all of * the document observers. * + * Since nsIStyleRule objects are immutable, there is a new object + * replacing the old one. However, the use of this method (rather + * than StyleRuleAdded and StyleRuleRemoved) implies that the new rule + * matches the same elements and has the same priority (weight, + * origin, specificity) as the old one. (However, if it is a CSS + * style rule, there may be a change in whether it has an important + * rule.) + * * @param aDocument The document being observed * @param aStyleSheet the StyleSheet that contians the rule - * @param aStyleRule the rule that was modified - * @param aHint some possible info about the nature of the change + * @param aOldStyleRule The rule being removed. This rule may not be + * fully valid anymore -- however, it can still + * be used for pointer comparison and + * |QueryInterface|. + * @param aNewStyleRule The rule being added. */ NS_IMETHOD StyleRuleChanged(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) = 0; + nsIStyleRule* aOldStyleRule, + nsIStyleRule* aNewStyleRule) = 0; /** * A StyleRule has just been added to a style sheet. @@ -378,8 +389,8 @@ public: PRBool aApplicable); \ NS_IMETHOD StyleRuleChanged(nsIDocument* aDocument, \ nsIStyleSheet* aStyleSheet, \ - nsIStyleRule* aStyleRule, \ - nsChangeHint aHint); \ + nsIStyleRule* aOldStyleRule, \ + nsIStyleRule* aNewStyleRule); \ NS_IMETHOD StyleRuleAdded(nsIDocument* aDocument, \ nsIStyleSheet* aStyleSheet, \ nsIStyleRule* aStyleRule); \ @@ -515,9 +526,9 @@ _class::StyleSheetApplicableStateChanged(nsIDocument* aDocument, \ } \ NS_IMETHODIMP \ _class::StyleRuleChanged(nsIDocument* aDocument, \ - nsIStyleSheet* aStyleSheet, \ - nsIStyleRule* aStyleRule, \ - nsChangeHint aHint) \ + nsIStyleSheet* aStyleSheet, \ + nsIStyleRule* aOldStyleRule, \ + nsIStyleRule* aNewStyleRule) \ { \ return NS_OK; \ } \ diff --git a/mozilla/content/base/public/nsIStyleRule.h b/mozilla/content/base/public/nsIStyleRule.h index d10791c3e38..d67723f1241 100644 --- a/mozilla/content/base/public/nsIStyleRule.h +++ b/mozilla/content/base/public/nsIStyleRule.h @@ -51,13 +51,54 @@ struct nsRuleData; #define NS_ISTYLE_RULE_IID \ {0x40ae5c90, 0xad6a, 0x11d1, {0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}} +/** + * An object implementing |nsIStyleRule| (henceforth, a rule) represents + * immutable stylistic information that either applies or does not apply + * to a given element. It belongs to an object or group of objects that + * implement |nsIStyleSheet| and |nsIStyleRuleProcessor| (henceforth, a + * sheet). + * + * A rule becomes relevant to the computation of style data when + * |nsIStyleRuleProcessor::RulesMatching| creates a rule node that + * points to the rule. (A rule node, |nsRuleNode|, is a node in the + * rule tree, which is a lexicographic tree indexed by rules. The path + * from the root of the rule tree to the |nsRuleNode| for a given + * |nsStyleContext| contains exactly the rules that match the element + * that the style context is for, in priority (weight, origin, + * specificity) order.) + * + * The computation of style data uses the rule tree, which calls + * |nsIStyleRule::MapRuleInfoInto| below. + * + * It is worth emphasizing that the data represented by a rule + * implementation are immutable. When the data need to be changed, a + * new rule object must be created. Failing to do this will lead to + * bugs in the handling of dynamic style changes, since the rule tree + * caches the results of |MapRuleInfoInto|. + * + * |nsIStyleRule| objects are owned by |nsRuleNode| objects (in addition + * to typically being owned by their sheet), which are in turn garbage + * collected (with the garbage collection roots being style contexts). + */ + + class nsIStyleRule : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISTYLE_RULE_IID) NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const = 0; - // The new mapping function. + /** + * |nsIStyleRule::MapRuleInfoInto| is a request to copy all stylistic + * data represented by the rule that: + * + are relevant for |aRuleData->mSID| (the style struct ID) + * + are not already filled into the data struct + * into the appropriate data struct in |aRuleData|. It is important + * that only empty data are filled in, since the rule tree is walked + * from highest priority rule to least, so that the walk can stop if + * all needed data are found. Thus overwriting non-empty data will + * break CSS cascading rules. + */ NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData)=0; #ifdef DEBUG diff --git a/mozilla/content/base/src/nsDocument.cpp b/mozilla/content/base/src/nsDocument.cpp index a3f49784477..95bfea94b54 100644 --- a/mozilla/content/base/src/nsDocument.cpp +++ b/mozilla/content/base/src/nsDocument.cpp @@ -2170,7 +2170,8 @@ nsDocument::AttributeChanged(nsIContent* aChild, PRInt32 aNameSpaceID, NS_IMETHODIMP nsDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, nsChangeHint aHint) + nsIStyleRule* aOldStyleRule, + nsIStyleRule* aNewStyleRule) { PRInt32 i; @@ -2183,7 +2184,7 @@ nsDocument::StyleRuleChanged(nsIStyleSheet* aStyleSheet, // XXXbz We should _not_ be calling BeginUpdate from in here! The // caller of StyleRuleChanged should do that! observer->BeginUpdate(this); - observer->StyleRuleChanged(this, aStyleSheet, aStyleRule, aHint); + observer->StyleRuleChanged(this, aStyleSheet, aOldStyleRule, aNewStyleRule); // Make sure that the observer didn't remove itself during the // notification. If it did, update our index and count. diff --git a/mozilla/content/base/src/nsDocument.h b/mozilla/content/base/src/nsDocument.h index 0d151bac1fe..1326f2fe74b 100644 --- a/mozilla/content/base/src/nsDocument.h +++ b/mozilla/content/base/src/nsDocument.h @@ -195,8 +195,8 @@ public: PRBool aApplicable) { return NS_OK; } NS_IMETHOD StyleRuleChanged(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) { return NS_OK; } + nsIStyleRule* aOldStyleRule, + nsIStyleRule* aNewStyleRule) { return NS_OK; } NS_IMETHOD StyleRuleAdded(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) { return NS_OK; } @@ -477,8 +477,8 @@ public: PRInt32 aIndexInContainer); NS_IMETHOD StyleRuleChanged(nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint); // See nsStyleConsts fot hint values + nsIStyleRule* aOldStyleRule, + nsIStyleRule* aNewStyleRule); NS_IMETHOD StyleRuleAdded(nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule); NS_IMETHOD StyleRuleRemoved(nsIStyleSheet* aStyleSheet, diff --git a/mozilla/content/base/src/nsRuleNode.cpp b/mozilla/content/base/src/nsRuleNode.cpp index 1bb258619e1..f26df07f013 100644 --- a/mozilla/content/base/src/nsRuleNode.cpp +++ b/mozilla/content/base/src/nsRuleNode.cpp @@ -553,74 +553,31 @@ nsRuleNode::PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched) return NS_OK; } -nsresult -nsRuleNode::ClearCachedData(nsIStyleRule* aRule) -{ - NS_ASSERTION(aRule, "you should be using ClearCachedDataInSubtree"); - - nsRuleNode* ruleDest = this; - while (ruleDest) { - if (ruleDest->mRule == aRule) - break; - ruleDest = ruleDest->mParent; - } - - if (ruleDest) { - NS_ASSERTION(ruleDest->mParent, "node must not be root"); - - // The rule was contained along our branch. We need to blow away - // all cached data along this path. Note that, because of the definition - // of inline style, all nodes along this path must have exactly one child. This - // is not a bushy subtree, and so we know that by clearing this path, we've - // invalidated everything that we need to. - // XXXldb What about !important :hover rules, and such? - nsRuleNode* curr = this; - while (curr) { - curr->mNoneBits &= ~NS_STYLE_INHERIT_MASK; - curr->mDependentBits &= ~NS_STYLE_INHERIT_MASK; - if (curr->mStyleData.mResetData || curr->mStyleData.mInheritedData) - curr->mStyleData.Destroy(0, mPresContext); - - if (curr == ruleDest) - break; - - curr = curr->mParent; - } - } - - return NS_OK; -} - PR_STATIC_CALLBACK(PLDHashOperator) -ClearCachedDataInSubtreeHelper(PLDHashTable *table, PLDHashEntryHdr *hdr, +ClearStyleDataHelper(PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void *arg) { ChildrenHashEntry *entry = NS_STATIC_CAST(ChildrenHashEntry*, hdr); - nsIStyleRule* rule = NS_STATIC_CAST(nsIStyleRule*, arg); - entry->mRuleNode->ClearCachedDataInSubtree(rule); + entry->mRuleNode->ClearStyleData(); return PL_DHASH_NEXT; } nsresult -nsRuleNode::ClearCachedDataInSubtree(nsIStyleRule* aRule) +nsRuleNode::ClearStyleData() { - if (aRule == nsnull || mRule == aRule) { - // We have a match. Blow away all data stored at this node. - if (mStyleData.mResetData || mStyleData.mInheritedData) - mStyleData.Destroy(0, mPresContext); + // Blow away all data stored at this node. + if (mStyleData.mResetData || mStyleData.mInheritedData) + mStyleData.Destroy(0, mPresContext); - mNoneBits &= ~NS_STYLE_INHERIT_MASK; - mDependentBits &= ~NS_STYLE_INHERIT_MASK; - - aRule = nsnull; // Cause everything to be blown away in the descendants. - } + mNoneBits &= ~NS_STYLE_INHERIT_MASK; + mDependentBits &= ~NS_STYLE_INHERIT_MASK; if (ChildrenAreHashed()) PL_DHashTableEnumerate(ChildrenHash(), - ClearCachedDataInSubtreeHelper, aRule); + ClearStyleDataHelper, nsnull); else for (nsRuleList* curr = ChildrenList(); curr; curr = curr->mNext) - curr->mRuleNode->ClearCachedDataInSubtree(aRule); + curr->mRuleNode->ClearStyleData(); return NS_OK; } @@ -649,11 +606,7 @@ nsRuleNode::PropagateNoneBit(PRUint32 aBit, nsRuleNode* aHighestNode) inline void nsRuleNode::PropagateDependentBit(PRUint32 aBit, nsRuleNode* aHighestNode) { - if (mDependentBits & aBit) - return; // Already set. - - nsRuleNode* curr = this; - while (curr != aHighestNode) { + for (nsRuleNode* curr = this; curr != aHighestNode; curr = curr->mParent) { if (curr->mDependentBits & aBit) { #ifdef DEBUG while (curr != aHighestNode) { @@ -665,7 +618,6 @@ nsRuleNode::PropagateDependentBit(PRUint32 aBit, nsRuleNode* aHighestNode) } curr->mDependentBits |= aBit; - curr = curr->mParent; } } @@ -1148,223 +1100,223 @@ nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, } const nsStyleStruct* -nsRuleNode::GetDisplayData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetDisplayData(nsStyleContext* aContext) { nsRuleDataDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Display, mPresContext, aContext); ruleData.mDisplayData = &displayData; - return WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData, aComputeData); + return WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData); } const nsStyleStruct* -nsRuleNode::GetVisibilityData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetVisibilityData(nsStyleContext* aContext) { nsRuleDataDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Visibility, mPresContext, aContext); ruleData.mDisplayData = &displayData; - return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData, aComputeData); + return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData); } const nsStyleStruct* -nsRuleNode::GetTextData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetTextData(nsStyleContext* aContext) { nsRuleDataText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Text, mPresContext, aContext); ruleData.mTextData = &textData; - return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData, aComputeData); + return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData); } const nsStyleStruct* -nsRuleNode::GetTextResetData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetTextResetData(nsStyleContext* aContext) { nsRuleDataText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TextReset, mPresContext, aContext); ruleData.mTextData = &textData; - return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData, aComputeData); + return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData); } const nsStyleStruct* -nsRuleNode::GetUserInterfaceData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetUserInterfaceData(nsStyleContext* aContext) { nsRuleDataUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UserInterface, mPresContext, aContext); ruleData.mUserInterfaceData = &uiData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData, aComputeData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData); uiData.mCursor = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetUIResetData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetUIResetData(nsStyleContext* aContext) { nsRuleDataUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UIReset, mPresContext, aContext); ruleData.mUserInterfaceData = &uiData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData, aComputeData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData); uiData.mKeyEquivalent = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetFontData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetFontData(nsStyleContext* aContext) { nsRuleDataFont fontData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Font, mPresContext, aContext); ruleData.mFontData = &fontData; - return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData, aComputeData); + return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData); } const nsStyleStruct* -nsRuleNode::GetColorData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetColorData(nsStyleContext* aContext) { nsRuleDataColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Color, mPresContext, aContext); ruleData.mColorData = &colorData; - return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData, aComputeData); + return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData); } const nsStyleStruct* -nsRuleNode::GetBackgroundData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetBackgroundData(nsStyleContext* aContext) { nsRuleDataColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Background, mPresContext, aContext); ruleData.mColorData = &colorData; - return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData, aComputeData); + return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData); } const nsStyleStruct* -nsRuleNode::GetMarginData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetMarginData(nsStyleContext* aContext) { nsRuleDataMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Margin, mPresContext, aContext); ruleData.mMarginData = &marginData; - return WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData, aComputeData); + return WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData); } const nsStyleStruct* -nsRuleNode::GetBorderData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetBorderData(nsStyleContext* aContext) { nsRuleDataMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Border, mPresContext, aContext); ruleData.mMarginData = &marginData; - return WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData, aComputeData); + return WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData); } const nsStyleStruct* -nsRuleNode::GetPaddingData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetPaddingData(nsStyleContext* aContext) { nsRuleDataMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Padding, mPresContext, aContext); ruleData.mMarginData = &marginData; - return WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData, aComputeData); + return WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData); } const nsStyleStruct* -nsRuleNode::GetOutlineData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetOutlineData(nsStyleContext* aContext) { nsRuleDataMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Outline, mPresContext, aContext); ruleData.mMarginData = &marginData; - return WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData, aComputeData); + return WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData); } const nsStyleStruct* -nsRuleNode::GetListData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetListData(nsStyleContext* aContext) { nsRuleDataList listData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_List, mPresContext, aContext); ruleData.mListData = &listData; - return WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData, aComputeData); + return WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData); } const nsStyleStruct* -nsRuleNode::GetPositionData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetPositionData(nsStyleContext* aContext) { nsRuleDataPosition posData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Position, mPresContext, aContext); ruleData.mPositionData = &posData; - return WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData, aComputeData); + return WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData); } const nsStyleStruct* -nsRuleNode::GetTableData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetTableData(nsStyleContext* aContext) { nsRuleDataTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Table, mPresContext, aContext); ruleData.mTableData = &tableData; - return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData, aComputeData); + return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData); } const nsStyleStruct* -nsRuleNode::GetTableBorderData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetTableBorderData(nsStyleContext* aContext) { nsRuleDataTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TableBorder, mPresContext, aContext); ruleData.mTableData = &tableData; - return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData, aComputeData); + return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData); } const nsStyleStruct* -nsRuleNode::GetContentData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetContentData(nsStyleContext* aContext) { nsRuleDataContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Content, mPresContext, aContext); ruleData.mContentData = &contentData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData, aComputeData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData); contentData.mCounterIncrement = contentData.mCounterReset = nsnull; contentData.mContent = nsnull; // We are sharing with some style rule. It really owns the data. return res; } const nsStyleStruct* -nsRuleNode::GetQuotesData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetQuotesData(nsStyleContext* aContext) { nsRuleDataContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Quotes, mPresContext, aContext); ruleData.mContentData = &contentData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData, aComputeData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData); contentData.mQuotes = nsnull; // We are sharing with some style rule. It really owns the data. return res; } const nsStyleStruct* -nsRuleNode::GetXULData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetXULData(nsStyleContext* aContext) { nsRuleDataXUL xulData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_XUL, mPresContext, aContext); ruleData.mXULData = &xulData; - return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData, aComputeData); + return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData); } #ifdef MOZ_SVG const nsStyleStruct* -nsRuleNode::GetSVGData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetSVGData(nsStyleContext* aContext) { nsRuleDataSVG svgData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_SVG, mPresContext, aContext); ruleData.mSVGData = &svgData; - return WalkRuleTree(eStyleStruct_SVG, aContext, &ruleData, &svgData, aComputeData); + return WalkRuleTree(eStyleStruct_SVG, aContext, &ruleData, &svgData); } #endif @@ -1372,8 +1324,7 @@ const nsStyleStruct* nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, nsStyleContext* aContext, nsRuleData* aRuleData, - nsRuleDataStruct* aSpecificData, - PRBool aComputeData) + nsRuleDataStruct* aSpecificData) { // We start at the most specific rule in the tree. nsStyleStruct* startStruct = nsnull; @@ -1496,9 +1447,6 @@ nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, } // We need to compute the data from the information that the rules specified. - if (!aComputeData) - return nsnull; - ComputeStyleDataFn fn = gComputeStyleDataFn[aSID]; const nsStyleStruct* res = (this->*fn)(startStruct, *aSpecificData, aContext, highestNode, detail, !aRuleData->mCanStoreInRuleTree); @@ -4491,14 +4439,17 @@ nsRuleNode::GetStyleData(nsStyleStructID aSID, NS_NOTREACHED("dependent bits set but no cached struct present"); } + if (!aComputeData) + return nsnull; + // Nothing is cached. We'll have to delve further and examine our rules. GetStyleDataFn fn = gGetStyleDataFn[aSID]; if (!fn) { NS_NOTREACHED("unknown style struct requested"); return nsnull; } - data = (this->*fn)(aContext, aComputeData); - if (data || !aComputeData) + data = (this->*fn)(aContext); + if (data) return data; NS_NOTREACHED("could not create style struct"); diff --git a/mozilla/content/base/src/nsStyleContext.cpp b/mozilla/content/base/src/nsStyleContext.cpp index 810984b4290..f6daeb03e54 100644 --- a/mozilla/content/base/src/nsStyleContext.cpp +++ b/mozilla/content/base/src/nsStyleContext.cpp @@ -396,27 +396,20 @@ nsStyleContext::ApplyStyleFixups(nsIPresContext* aPresContext) } void -nsStyleContext::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule) +nsStyleContext::ClearStyleData(nsIPresContext* aPresContext) { - PRBool matched = PR_TRUE; - if (aRule) - mRuleNode->PathContainsRule(aRule, &matched); - - if (matched) { - // First we need to clear out all of our style data. - if (mCachedStyleData.mResetData || mCachedStyleData.mInheritedData) - mCachedStyleData.Destroy(mBits, aPresContext); + // First we need to clear out all of our style data. + if (mCachedStyleData.mResetData || mCachedStyleData.mInheritedData) + mCachedStyleData.Destroy(mBits, aPresContext); - mBits = 0; // Clear all bits. - aRule = nsnull; // Force all structs to be blown away in the children. - } + mBits = 0; // Clear all bits. ApplyStyleFixups(aPresContext); if (mChild) { nsStyleContext* child = mChild; do { - child->ClearStyleData(aPresContext, aRule); + child->ClearStyleData(aPresContext); child = child->mNextSibling; } while (mChild != child); } @@ -424,7 +417,7 @@ nsStyleContext::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule if (mEmptyChild) { nsStyleContext* child = mEmptyChild; do { - child->ClearStyleData(aPresContext, aRule); + child->ClearStyleData(aPresContext); child = child->mNextSibling; } while (mEmptyChild != child); } diff --git a/mozilla/content/base/src/nsStyleSet.cpp b/mozilla/content/base/src/nsStyleSet.cpp index be03afc5468..9baf2b190e9 100644 --- a/mozilla/content/base/src/nsStyleSet.cpp +++ b/mozilla/content/base/src/nsStyleSet.cpp @@ -195,7 +195,7 @@ public: virtual nsresult GetRuleTree(nsRuleNode** aResult); - virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule); + virtual nsresult ClearStyleData(nsIPresContext* aPresContext); virtual nsresult GetStyleFrameConstruction(nsIStyleFrameConstruction** aResult) { *aResult = mFrameConstructor; @@ -254,20 +254,6 @@ public: PRInt32 aModType, nsChangeHint aHint); // See nsStyleConsts fot hint values - // xxx style rules enumeration - - // Style change notifications - NS_IMETHOD StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint); // See nsStyleConsts fot hint values - NS_IMETHOD StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - NS_IMETHOD StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - // Notification that we were unable to render a replaced element. NS_IMETHOD CantRenderReplacedElement(nsIPresContext* aPresContext, nsIFrame* aFrame); @@ -1504,30 +1490,13 @@ StyleSetImpl::GetDefaultStyleData() } nsresult -StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule) +StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext) { - // XXXdwh This is not terribly fast, but fortunately this case is rare (and often a full tree - // invalidation anyway). Improving performance here would involve a footprint - // increase. Mappings from rule nodes to their associated style contexts as well as - // mappings from rules to their associated rule nodes would enable us to avoid the two - // tree walks that occur here. - - // Crawl the entire rule tree and blow away all data for rule nodes (and their descendants) - // that have the given rule. if (mRuleTree) - mRuleTree->ClearCachedDataInSubtree(aRule); - - // We need to crawl the entire style context tree, and for each style context we need - // to see if the specified rule is matched. If so, that context and all its descendant - // contexts must have their data wiped. - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - nsIFrame* rootFrame; - shell->GetRootFrame(&rootFrame); - if (rootFrame) { - nsStyleContext* rootContext = rootFrame->GetStyleContext(); - if (rootContext) - rootContext->ClearStyleData(aPresContext, aRule); + mRuleTree->ClearStyleData(); + + for (PRInt32 i = mRoots.Count() - 1; i >= 0; --i) { + NS_STATIC_CAST(nsStyleContext*,mRoots[i])->ClearStyleData(aPresContext); } return NS_OK; @@ -1761,33 +1730,6 @@ StyleSetImpl::AttributeChanged(nsIPresContext* aPresContext, aNameSpaceID, aAttribute, aModType, aHint); } - -// Style change notifications -NS_IMETHODIMP -StyleSetImpl::StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) -{ - return mFrameConstructor->StyleRuleChanged(aPresContext, aStyleSheet, aStyleRule, aHint); -} - -NS_IMETHODIMP -StyleSetImpl::StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) -{ - return mFrameConstructor->StyleRuleAdded(aPresContext, aStyleSheet, aStyleRule); -} - -NS_IMETHODIMP -StyleSetImpl::StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) -{ - return mFrameConstructor->StyleRuleRemoved(aPresContext, aStyleSheet, aStyleRule); -} - NS_IMETHODIMP StyleSetImpl::CantRenderReplacedElement(nsIPresContext* aPresContext, nsIFrame* aFrame) diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index ef3f235f818..2f292ab10ff 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -5448,7 +5448,8 @@ HTMLContentSink::StyleSheetApplicableStateChanged(nsIDocument *aDocument, NS_IMETHODIMP HTMLContentSink::StyleRuleChanged(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, nsChangeHint aHint) + nsIStyleRule* aOldStyleRule, + nsIStyleRule* aNewStyleRule) { return NS_OK; } diff --git a/mozilla/content/html/style/public/nsICSSStyleSheet.h b/mozilla/content/html/style/public/nsICSSStyleSheet.h index 6ccaa54f77d..7c863be0dba 100644 --- a/mozilla/content/html/style/public/nsICSSStyleSheet.h +++ b/mozilla/content/html/style/public/nsICSSStyleSheet.h @@ -64,12 +64,14 @@ public: NS_IMETHOD PrependStyleRule(nsICSSRule* aRule) = 0; NS_IMETHOD AppendStyleRule(nsICSSRule* aRule) = 0; + NS_IMETHOD ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) = 0; NS_IMETHOD StyleRuleCount(PRInt32& aCount) const = 0; NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const = 0; NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) = 0; NS_IMETHOD InsertRuleIntoGroup(const nsAString & aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval) = 0; + NS_IMETHOD ReplaceRuleInGroup(nsICSSGroupRule* aGroup, nsICSSRule* aOld, nsICSSRule* aNew) = 0; NS_IMETHOD StyleSheetCount(PRInt32& aCount) const = 0; NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsICSSStyleSheet*& aSheet) const = 0; diff --git a/mozilla/content/html/style/src/nsCSSParser.cpp b/mozilla/content/html/style/src/nsCSSParser.cpp index b248ffea8a2..e52cb771735 100644 --- a/mozilla/content/html/style/src/nsCSSParser.cpp +++ b/mozilla/content/html/style/src/nsCSSParser.cpp @@ -640,12 +640,11 @@ CSSParserImpl::ParseStyleAttribute(const nsAString& aAttributeValue, if (declaration) { // Create a style rule for the delcaration nsICSSStyleRule* rule = nsnull; - rv = NS_NewCSSStyleRule(&rule, nsnull); + rv = NS_NewCSSStyleRule(&rule, nsnull, declaration); if (NS_FAILED(rv)) { declaration->RuleAbort(); return rv; } - rule->SetDeclaration(declaration); *aResult = rule; } else { @@ -1473,14 +1472,13 @@ PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode, RuleAppendFunc aAppendFu // Translate the selector list and declaration block into style data nsCOMPtr rule; - NS_NewCSSStyleRule(getter_AddRefs(rule), slist); + NS_NewCSSStyleRule(getter_AddRefs(rule), slist, declaration); if (!rule) { aErrorCode = NS_ERROR_OUT_OF_MEMORY; delete slist; return PR_FALSE; } rule->SetLineNumber(linenum); - rule->SetDeclaration(declaration); (*aAppendFunc)(rule, aData); return PR_TRUE; diff --git a/mozilla/content/html/style/src/nsCSSRules.cpp b/mozilla/content/html/style/src/nsCSSRules.cpp index aed43a7e994..a70066583fe 100644 --- a/mozilla/content/html/style/src/nsCSSRules.cpp +++ b/mozilla/content/html/style/src/nsCSSRules.cpp @@ -662,6 +662,7 @@ public: NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const; NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex); NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules); + NS_IMETHOD ReplaceStyleRule(nsICSSRule *aOld, nsICSSRule *aNew); // nsIDOMCSSRule interface NS_DECL_NSIDOMCSSRULE @@ -872,6 +873,8 @@ CSSMediaRuleImpl::AppendStyleRule(nsICSSRule* aRule) aRule->SetStyleSheet(mSheet); aRule->SetParentRule(this); if (mSheet) { + // XXXldb Shouldn't we be using |WillDirty| and |DidDirty| (and + // shouldn't |SetModified| be removed? mSheet->SetModified(PR_TRUE); } } @@ -952,6 +955,18 @@ CSSMediaRuleImpl::InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) return NS_OK; } +NS_IMETHODIMP +CSSMediaRuleImpl::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) +{ + PRInt32 index = mRules->IndexOf(aOld); + NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); + mRules->ReplaceElementAt(aNew, index); + aNew->SetStyleSheet(mSheet); + aNew->SetParentRule(this); + aOld->SetStyleSheet(nsnull); + aOld->SetParentRule(nsnull); + return NS_OK; +} nsresult NS_NewCSSMediaRule(nsICSSMediaRule** aInstancePtrResult) diff --git a/mozilla/content/html/style/src/nsCSSStyleRule.cpp b/mozilla/content/html/style/src/nsCSSStyleRule.cpp index e72cabd41df..b428220ca60 100644 --- a/mozilla/content/html/style/src/nsCSSStyleRule.cpp +++ b/mozilla/content/html/style/src/nsCSSStyleRule.cpp @@ -854,7 +854,7 @@ CSSImportantRule::List(FILE* out, PRInt32 aIndent) const } #endif -// -- nsDOMStyleRuleDeclaration ------------------------------- +// -- DOMCSSDeclarationImpl ------------------------------- class DOMCSSDeclarationImpl : public nsDOMCSSDeclaration { @@ -862,24 +862,14 @@ public: DOMCSSDeclarationImpl(nsICSSStyleRule *aRule); ~DOMCSSDeclarationImpl(void); - NS_IMETHOD RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn); - virtual void DropReference(void); virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate); - virtual nsresult GetCSSParsingEnvironment(nsICSSStyleRule* aRule, - nsICSSStyleSheet** aSheet, - nsIDocument** aDocument, - nsIURI** aURI, + virtual nsresult GetCSSParsingEnvironment(nsIURI** aURI, nsICSSLoader** aCSSLoader, nsICSSParser** aCSSParser); - virtual nsresult ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue); - virtual nsresult ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl); virtual nsresult GetParent(nsISupports **aParent); + virtual nsresult DeclarationChanged(); protected: nsICSSStyleRule *mRule; @@ -901,55 +891,6 @@ DOMCSSDeclarationImpl::~DOMCSSDeclarationImpl(void) MOZ_COUNT_DTOR(DOMCSSDeclarationImpl); } -NS_IMETHODIMP -DOMCSSDeclarationImpl::RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn) -{ - aReturn.Truncate(); - - nsCSSDeclaration* decl; - nsresult rv = GetCSSDeclaration(&decl, PR_TRUE); - - if (NS_SUCCEEDED(rv) && decl) { - nsCOMPtr cssSheet; - nsCOMPtr owningDoc; - if (mRule) { - nsCOMPtr sheet; - mRule->GetStyleSheet(*getter_AddRefs(sheet)); - cssSheet = do_QueryInterface(sheet); - if (sheet) { - sheet->GetOwningDocument(*getter_AddRefs(owningDoc)); - } - } - if (owningDoc) { - owningDoc->BeginUpdate(); - } - nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName); - - decl->GetValue(prop, aReturn); - - rv = decl->RemoveProperty(prop); - - if (NS_SUCCEEDED(rv)) { - if (cssSheet) { - cssSheet->SetModified(PR_TRUE); - } - if (owningDoc) { - owningDoc->StyleRuleChanged(cssSheet, mRule, nsCSSProps::kHintTable[prop]); - } - } else { - // If we tried to remove an invalid property or a property that wasn't - // set we simply return success and an empty string - rv = NS_OK; - } - if (owningDoc) { - owningDoc->EndUpdate(); - } - } - - return rv; -} - void DOMCSSDeclarationImpl::DropReference(void) { @@ -972,38 +913,34 @@ DOMCSSDeclarationImpl::GetCSSDeclaration(nsCSSDeclaration **aDecl, /* * This is a utility function. It will only fail if it can't get a - * parser. This means it can return NS_OK without all of aSheet, - * aDocument, aURI, aCSSLoader being initialized + * parser. This means it can return NS_OK without aURI or aCSSLoader + * being initialized. */ nsresult -DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsICSSStyleRule* aRule, - nsICSSStyleSheet** aSheet, - nsIDocument** aDocument, - nsIURI** aURI, +DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsIURI** aURI, nsICSSLoader** aCSSLoader, nsICSSParser** aCSSParser) { // null out the out params since some of them may not get initialized below - *aSheet = nsnull; - *aDocument = nsnull; *aURI = nsnull; *aCSSLoader = nsnull; *aCSSParser = nsnull; nsresult result; nsCOMPtr sheet; - if (aRule) { - aRule->GetStyleSheet(*getter_AddRefs(sheet)); + if (mRule) { + mRule->GetStyleSheet(*getter_AddRefs(sheet)); if (sheet) { - CallQueryInterface(sheet, aSheet); - sheet->GetOwningDocument(*aDocument); sheet->GetURL(*aURI); + nsCOMPtr document; + sheet->GetOwningDocument(*getter_AddRefs(document)); + nsCOMPtr htmlContainer = + do_QueryInterface(document); + if (htmlContainer) { + htmlContainer->GetCSSLoader(*aCSSLoader); + NS_ASSERTION(*aCSSLoader, "Document with no CSS loader!"); + } } } - nsCOMPtr htmlContainer(do_QueryInterface(*aDocument)); - if (htmlContainer) { - htmlContainer->GetCSSLoader(*aCSSLoader); - } - NS_ASSERTION(*aCSSLoader || !*aDocument, "Document with no CSS loader!"); if (*aCSSLoader) { result = (*aCSSLoader)->GetParserFor(nsnull, aCSSParser); } else { @@ -1013,99 +950,6 @@ DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsICSSStyleRule* aRule, return result; } -nsresult -DOMCSSDeclarationImpl::ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue) -{ - nsCSSDeclaration* decl; - nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - if (!decl) { - return result; - } - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - nsCOMPtr cssSheet; - nsCOMPtr owningDoc; - result = GetCSSParsingEnvironment(mRule, - getter_AddRefs(cssSheet), - getter_AddRefs(owningDoc), - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - - if (NS_FAILED(result)) { - return result; - } - - nsChangeHint hint; - if (owningDoc) { - owningDoc->BeginUpdate(); - } - result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, &hint); - if (NS_SUCCEEDED(result)) { - if (cssSheet) { - cssSheet->SetModified(PR_TRUE); - } - if (owningDoc) { - owningDoc->StyleRuleChanged(cssSheet, mRule, hint); - owningDoc->EndUpdate(); - } - } - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - - return result; -} - -nsresult -DOMCSSDeclarationImpl::ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl) -{ - nsCSSDeclaration* decl; - nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - - if (decl) { - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - nsCOMPtr cssSheet; - nsCOMPtr owningDoc; - - result = GetCSSParsingEnvironment(mRule, - getter_AddRefs(cssSheet), - getter_AddRefs(owningDoc), - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - - if (NS_SUCCEEDED(result)) { - nsChangeHint hint; - result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, - aParseOnlyOneDecl, &hint, - aClearOldDecl); - - if (NS_SUCCEEDED(result)) { - if (cssSheet) { - cssSheet->SetModified(PR_TRUE); - } - if (owningDoc) { - owningDoc->StyleRuleChanged(cssSheet, mRule, hint); - } - } - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - } - } - - return result; -} - - - nsresult DOMCSSDeclarationImpl::GetParent(nsISupports **aParent) { @@ -1120,6 +964,37 @@ DOMCSSDeclarationImpl::GetParent(nsISupports **aParent) return NS_OK; } +nsresult +DOMCSSDeclarationImpl::DeclarationChanged() +{ + NS_PRECONDITION(mRule, + "can only be called when |GetCSSDeclaration| returned a declaration"); + + nsCOMPtr owningDoc; + nsCOMPtr sheet; + mRule->GetStyleSheet(*getter_AddRefs(sheet)); + if (sheet) { + sheet->GetOwningDocument(*getter_AddRefs(owningDoc)); + } + + if (owningDoc) { + // XXXldb Do we need to bother with this? We're now doing it in + // more places than we used to, but it probably doesn't matter... + owningDoc->BeginUpdate(); + } + + nsCOMPtr oldRule = mRule; + mRule = oldRule->DeclarationChanged(PR_TRUE).get(); + nsrefcnt cnt = mRule->Release(); + NS_ASSERTION(cnt != 0, "container didn't take ownership"); + + if (owningDoc) { + owningDoc->StyleRuleChanged(sheet, oldRule, mRule); + owningDoc->EndUpdate(); + } + return NS_OK; +} + // -- nsCSSStyleRule ------------------------------- class CSSStyleRuleImpl : public nsCSSRule, @@ -1127,8 +1002,15 @@ class CSSStyleRuleImpl : public nsCSSRule, public nsIDOMCSSStyleRule { public: - CSSStyleRuleImpl(nsCSSSelectorList* aSelector); + CSSStyleRuleImpl(nsCSSSelectorList* aSelector, + nsCSSDeclaration *aDeclaration); +private: + // for |Clone| CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy); + // for |DeclarationChanged| + CSSStyleRuleImpl(CSSStyleRuleImpl& aCopy, + nsCSSDeclaration *aDeclaration); +public: NS_DECL_ISUPPORTS_INHERITED @@ -1138,7 +1020,6 @@ public: virtual void SetLineNumber(PRUint32 aLineNumber); virtual nsCSSDeclaration* GetDeclaration(void) const; - virtual void SetDeclaration(nsCSSDeclaration* aDeclaration); virtual already_AddRefed GetImportantRule(void); @@ -1153,6 +1034,9 @@ public: NS_IMETHOD GetType(PRInt32& aType) const; NS_IMETHOD Clone(nsICSSRule*& aClone) const; + virtual already_AddRefed + DeclarationChanged(PRBool aHandleContainer); + // The new mapping function. NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData); @@ -1181,30 +1065,50 @@ protected: PRUint32 mLineNumber; }; -CSSStyleRuleImpl::CSSStyleRuleImpl(nsCSSSelectorList* aSelector) +CSSStyleRuleImpl::CSSStyleRuleImpl(nsCSSSelectorList* aSelector, + nsCSSDeclaration* aDeclaration) : nsCSSRule(), - mSelector(aSelector), mDeclaration(nsnull), + mSelector(aSelector), + mDeclaration(aDeclaration), mImportantRule(nsnull), mDOMDeclaration(nsnull) { + if (mDeclaration) + mDeclaration->AddRef(); } +// for |Clone| CSSStyleRuleImpl::CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy) : nsCSSRule(aCopy), mSelector(aCopy.mSelector ? aCopy.mSelector->Clone() : nsnull), - mDeclaration(nsnull), + mDeclaration(aCopy.mDeclaration ? aCopy.mDeclaration->Clone() : nsnull), mImportantRule(nsnull), mDOMDeclaration(nsnull) { - if (aCopy.mDeclaration) { - mDeclaration = aCopy.mDeclaration->Clone(); - if (nsnull != mDeclaration) { - mDeclaration->AddRef(); - } - } + if (mDeclaration) + mDeclaration->AddRef(); // rest is constructed lazily on existing data } +// for |DeclarationChanged| +CSSStyleRuleImpl::CSSStyleRuleImpl(CSSStyleRuleImpl& aCopy, + nsCSSDeclaration* aDeclaration) + : nsCSSRule(aCopy), + mSelector(aCopy.mSelector), + mDeclaration(aDeclaration), + mImportantRule(nsnull), + mDOMDeclaration(aCopy.mDOMDeclaration) +{ + // The DOM declaration is replacing |aCopy| with |this|, so transfer + // the reverse pointer as well. + aCopy.mDOMDeclaration = nsnull; + + // Transfer ownership of selector and declaration: + NS_ASSERTION(aDeclaration == aCopy.mDeclaration, "declaration mismatch"); + aCopy.mSelector = nsnull; + aCopy.mDeclaration = nsnull; +} + CSSStyleRuleImpl::~CSSStyleRuleImpl(void) { @@ -1259,20 +1163,7 @@ void CSSStyleRuleImpl::SetLineNumber(PRUint32 aLineNumber) nsCSSDeclaration* CSSStyleRuleImpl::GetDeclaration(void) const { - nsCSSDeclaration* result = mDeclaration; - return result; -} - -void CSSStyleRuleImpl::SetDeclaration(nsCSSDeclaration* aDeclaration) -{ - if (mDeclaration != aDeclaration) { - NS_IF_RELEASE(mImportantRule); - if (nsnull != mDeclaration) { - mDeclaration->Release(); - } - mDeclaration = aDeclaration; - mDeclaration->AddRef(); - } + return mDeclaration; } already_AddRefed CSSStyleRuleImpl::GetImportantRule(void) @@ -1326,11 +1217,32 @@ NS_IMETHODIMP CSSStyleRuleImpl::Clone(nsICSSRule*& aClone) const { CSSStyleRuleImpl* clone = new CSSStyleRuleImpl(*this); - if (clone) { - return CallQueryInterface(clone, &aClone); + if (!clone) { + aClone = nsnull; + return NS_ERROR_OUT_OF_MEMORY; } - aClone = nsnull; - return NS_ERROR_OUT_OF_MEMORY; + return CallQueryInterface(clone, &aClone); +} + +/* virtual */ already_AddRefed +CSSStyleRuleImpl::DeclarationChanged(PRBool aHandleContainer) +{ + CSSStyleRuleImpl* clone = new CSSStyleRuleImpl(*this, mDeclaration); + if (!clone) { + return nsnull; + } + + NS_ADDREF(clone); // for return + + if (aHandleContainer) { + if (mParentRule) { + mSheet->ReplaceRuleInGroup(mParentRule, this, clone); + } else { + mSheet->ReplaceStyleRule(this, clone); + } + } + + return clone; } NS_IMETHODIMP @@ -1457,13 +1369,10 @@ CSSStyleRuleImpl::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) nsresult NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult, - nsCSSSelectorList* aSelector) + nsCSSSelectorList* aSelector, + nsCSSDeclaration* aDeclaration) { - if (aInstancePtrResult == nsnull) { - return NS_ERROR_NULL_POINTER; - } - - CSSStyleRuleImpl *it = new CSSStyleRuleImpl(aSelector); + CSSStyleRuleImpl *it = new CSSStyleRuleImpl(aSelector, aDeclaration); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp index d93fa334b6b..9fc2ff1945c 100644 --- a/mozilla/content/html/style/src/nsCSSStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsCSSStyleSheet.cpp @@ -819,6 +819,7 @@ public: NS_IMETHOD ClearMedia(void); NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex); NS_IMETHOD InsertRuleIntoGroup(const nsAString& aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval); + NS_IMETHOD ReplaceRuleInGroup(nsICSSGroupRule* aGroup, nsICSSRule* aOld, nsICSSRule* aNew); NS_IMETHOD GetApplicable(PRBool& aApplicable) const; @@ -847,6 +848,7 @@ public: // XXX do these belong here or are they generic? NS_IMETHOD PrependStyleRule(nsICSSRule* aRule); NS_IMETHOD AppendStyleRule(nsICSSRule* aRule); + NS_IMETHOD ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew); NS_IMETHOD StyleRuleCount(PRInt32& aCount) const; NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const; @@ -1354,7 +1356,8 @@ DOMMediaListImpl::EndMediaChange(void) mStyleSheet->DidDirty(); rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); NS_ENSURE_SUCCESS(rv, rv); - rv = doc->StyleRuleChanged(mStyleSheet, nsnull, NS_STYLE_HINT_RECONSTRUCT_ALL); + // XXXldb Pass something meaningful? + rv = doc->StyleRuleChanged(mStyleSheet, nsnull, nsnull); NS_ENSURE_SUCCESS(rv, rv); rv = doc->EndUpdate(); NS_ENSURE_SUCCESS(rv, rv); @@ -2159,6 +2162,32 @@ CSSStyleSheetImpl::AppendStyleRule(nsICSSRule* aRule) return NS_OK; } +NS_IMETHODIMP +CSSStyleSheetImpl::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) +{ + NS_PRECONDITION(mInner->mOrderedRules, "can't have old rule"); + NS_PRECONDITION(mInner && mInner->mComplete, + "No replacing in an incomplete sheet!"); + + if (NS_SUCCEEDED(WillDirty())) { + PRInt32 index = mInner->mOrderedRules->IndexOf(aOld); + NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); + mInner->mOrderedRules->ReplaceElementAt(aNew, index); + + aNew->SetStyleSheet(this); + aOld->SetStyleSheet(nsnull); + DidDirty(); +#ifdef DEBUG + PRInt32 type = nsICSSRule::UNKNOWN_RULE; + aNew->GetType(type); + NS_ASSERTION(nsICSSRule::NAMESPACE_RULE != type, "not yet implemented"); + aOld->GetType(type); + NS_ASSERTION(nsICSSRule::NAMESPACE_RULE != type, "not yet implemented"); +#endif + } + return NS_OK; +} + NS_IMETHODIMP CSSStyleSheetImpl::StyleRuleCount(PRInt32& aCount) const { @@ -2981,6 +3010,29 @@ CSSStyleSheetImpl::InsertRuleIntoGroup(const nsAString & aRule, nsICSSGroupRule* return NS_OK; } +NS_IMETHODIMP +CSSStyleSheetImpl::ReplaceRuleInGroup(nsICSSGroupRule* aGroup, + nsICSSRule* aOld, nsICSSRule* aNew) +{ + nsresult result; + NS_PRECONDITION(mInner && mInner->mComplete, + "No replacing in an incomplete sheet!"); +#ifdef DEBUG + { + nsCOMPtr domGroup(do_QueryInterface(aGroup)); + nsCOMPtr groupSheet; + domGroup->GetParentStyleSheet(getter_AddRefs(groupSheet)); + NS_ASSERTION(this == groupSheet, "group doesn't belong to this sheet"); + } +#endif + result = WillDirty(); + NS_ENSURE_SUCCESS(result, result); + + result = aGroup->ReplaceStyleRule(aOld, aNew); + DidDirty(); + return result; +} + // nsICSSLoaderObserver implementation NS_IMETHODIMP CSSStyleSheetImpl::StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify) diff --git a/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.cpp b/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.cpp index ddadc3b3ea1..ca1e51a4d7c 100644 --- a/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.cpp +++ b/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.cpp @@ -68,35 +68,6 @@ nsDOMCSSAttributeDeclaration::~nsDOMCSSAttributeDeclaration() MOZ_COUNT_DTOR(nsDOMCSSAttributeDeclaration); } -NS_IMETHODIMP -nsDOMCSSAttributeDeclaration::RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn) -{ - aReturn.Truncate(); - - nsCSSDeclaration* decl; - nsresult rv = GetCSSDeclaration(&decl, PR_FALSE); - - if (NS_SUCCEEDED(rv) && decl) { - nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName); - - decl->GetValue(prop, aReturn); - - rv = decl->RemoveProperty(prop); - - if (NS_SUCCEEDED(rv)) { - rv = SetCSSDeclaration(decl, PR_TRUE, PR_TRUE); - } else { - // RemoveProperty will throw in all sorts of situations -- eg if - // the property is a shorthand one. Do not propagate its return - // value to callers. - rv = NS_OK; - } - } - - return rv; -} - void nsDOMCSSAttributeDeclaration::DropReference() { @@ -104,26 +75,25 @@ nsDOMCSSAttributeDeclaration::DropReference() } nsresult -nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration* aDecl, - PRBool aNotify, - PRBool aDeclOwnedByRule) +nsDOMCSSAttributeDeclaration::DeclarationChanged() { NS_ASSERTION(mContent, "Must have content node to set the decl!"); - NS_PRECONDITION(aDecl, "Null decl!"); - - nsCOMPtr cssRule; - nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsnull); - if (NS_FAILED(rv)) { - if (!aDeclOwnedByRule) { - aDecl->RuleAbort(); - } - return rv; + nsHTMLValue val; + nsresult rv = mContent->GetHTMLAttribute(nsHTMLAtoms::style, val); + NS_ASSERTION(rv == NS_CONTENT_ATTR_HAS_VALUE && + eHTMLUnit_ISupports == val.GetUnit(), + "content must have rule"); + nsCOMPtr oldRule = + do_QueryInterface(nsCOMPtr(val.GetISupportsValue())); + + nsCOMPtr newRule = oldRule->DeclarationChanged(PR_FALSE); + if (!newRule) { + return NS_ERROR_OUT_OF_MEMORY; } - cssRule->SetDeclaration(aDecl); return mContent->SetHTMLAttribute(nsHTMLAtoms::style, - nsHTMLValue(cssRule), - aNotify); + nsHTMLValue(newRule), + PR_TRUE); } nsresult @@ -152,7 +122,17 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, decl->RuleAbort(); return NS_ERROR_OUT_OF_MEMORY; } - result = SetCSSDeclaration(decl, PR_FALSE, PR_FALSE); + + nsCOMPtr cssRule; + result = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsnull, decl); + if (NS_FAILED(result)) { + decl->RuleAbort(); + return result; + } + + result = mContent->SetHTMLAttribute(nsHTMLAtoms::style, + nsHTMLValue(cssRule), + PR_FALSE); if (NS_SUCCEEDED(result)) { *aDecl = decl; } @@ -165,22 +145,21 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, /* * This is a utility function. It will only fail if it can't get a * parser. This means it can return NS_OK without aURI or aCSSLoader - * being initialized + * being initialized. */ nsresult -nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIContent* aContent, - nsIURI** aBaseURI, +nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIURI** aBaseURI, nsICSSLoader** aCSSLoader, nsICSSParser** aCSSParser) { - NS_ASSERTION(aContent, "Something is severely broken -- there should be an nsIContent here!"); + NS_ASSERTION(mContent, "Something is severely broken -- there should be an nsIContent here!"); // null out the out params since some of them may not get initialized below *aBaseURI = nsnull; *aCSSLoader = nsnull; *aCSSParser = nsnull; nsCOMPtr nodeInfo; - nsresult result = aContent->GetNodeInfo(getter_AddRefs(nodeInfo)); + nsresult result = mContent->GetNodeInfo(getter_AddRefs(nodeInfo)); if (NS_FAILED(result)) { return result; } @@ -214,85 +193,6 @@ nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIContent* aContent, return NS_OK; } -nsresult -nsDOMCSSAttributeDeclaration::ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue) -{ - nsCSSDeclaration* decl; - nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - - if (!decl) { - return result; - } - - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - - result = GetCSSParsingEnvironment(mContent, - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - if (NS_FAILED(result)) { - return result; - } - - nsChangeHint uselessHint = NS_STYLE_HINT_NONE; - result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, - &uselessHint); - if (NS_SUCCEEDED(result)) { - result = SetCSSDeclaration(decl, PR_TRUE, PR_TRUE); - } - - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - - return result; -} - -nsresult -nsDOMCSSAttributeDeclaration::ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl) -{ - nsCSSDeclaration* decl; - nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - - if (!decl) { - return result; - } - - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - - result = GetCSSParsingEnvironment(mContent, - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - - if (NS_FAILED(result)) { - return result; - } - - nsChangeHint uselessHint = NS_STYLE_HINT_NONE; - result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, - aParseOnlyOneDecl, - &uselessHint, - aClearOldDecl); - - if (NS_SUCCEEDED(result)) { - result = SetCSSDeclaration(decl, PR_TRUE, PR_TRUE); - } - - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - - return result; -} - nsresult nsDOMCSSAttributeDeclaration::GetParent(nsISupports **aParent) { diff --git a/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.h b/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.h index 1d2abb93c0e..97575e4e098 100644 --- a/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.h +++ b/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.h @@ -55,28 +55,18 @@ public: nsDOMCSSAttributeDeclaration(nsIHTMLContent *aContent); ~nsDOMCSSAttributeDeclaration(); - NS_IMETHOD RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn); - virtual void DropReference(); // If GetCSSDeclaration returns non-null, then the decl it returns // is owned by our current style rule. virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate); - virtual nsresult GetCSSParsingEnvironment(nsIContent* aContent, - nsIURI** aBaseURI, + virtual nsresult GetCSSParsingEnvironment(nsIURI** aBaseURI, nsICSSLoader** aCSSLoader, nsICSSParser** aCSSParser); - virtual nsresult ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue); - virtual nsresult ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl); virtual nsresult GetParent(nsISupports **aParent); protected: - nsresult SetCSSDeclaration(nsCSSDeclaration* aDecl, PRBool aNotify, - PRBool aDeclOwnedByRule); + virtual nsresult DeclarationChanged(); nsIHTMLContent *mContent; }; diff --git a/mozilla/content/html/style/src/nsDOMCSSDeclaration.cpp b/mozilla/content/html/style/src/nsDOMCSSDeclaration.cpp index 7f7f861b7f2..4ccba2920e5 100644 --- a/mozilla/content/html/style/src/nsDOMCSSDeclaration.cpp +++ b/mozilla/content/html/style/src/nsDOMCSSDeclaration.cpp @@ -39,6 +39,7 @@ #include "nsDOMCSSDeclaration.h" #include "nsIDOMCSSRule.h" #include "nsICSSParser.h" +#include "nsICSSLoader.h" #include "nsIStyleRule.h" #include "nsCSSDeclaration.h" #include "nsCSSProps.h" @@ -138,9 +139,10 @@ nsDOMCSSDeclaration::GetLength(PRUint32* aLength) nsCSSDeclaration *decl; nsresult result = GetCSSDeclaration(&decl, PR_FALSE); - *aLength = 0; - if ((NS_OK == result) && (nsnull != decl)) { + if (decl) { *aLength = decl->Count(); + } else { + *aLength = 0; } return result; @@ -182,7 +184,7 @@ nsDOMCSSDeclaration::Item(PRUint32 aIndex, nsAString& aReturn) nsresult result = GetCSSDeclaration(&decl, PR_FALSE); aReturn.SetLength(0); - if ((NS_OK == result) && (nsnull != decl)) { + if (decl) { result = decl->GetNthProperty(aIndex, aReturn); } @@ -197,8 +199,8 @@ nsDOMCSSDeclaration::GetPropertyValue(const nsAString& aPropertyName, nsCSSDeclaration *decl; nsresult result = GetCSSDeclaration(&decl, PR_FALSE); - aReturn.SetLength(0); - if ((NS_OK == result) && (nsnull != decl)) { + aReturn.Truncate(); + if (decl) { result = decl->GetValue(aPropertyName, aReturn); } @@ -211,18 +213,11 @@ nsDOMCSSDeclaration::GetPropertyPriority(const nsAString& aPropertyName, { nsCSSDeclaration *decl; nsresult result = GetCSSDeclaration(&decl, PR_FALSE); - PRBool isImportant = PR_FALSE; - if ((NS_OK == result) && (nsnull != decl)) { - isImportant = decl->GetValueIsImportant(aPropertyName); - } - - if ((NS_OK == result) && isImportant) { + aReturn.Truncate(); + if (decl && decl->GetValueIsImportant(aPropertyName)) { aReturn.Assign(NS_LITERAL_STRING("important")); } - else { - aReturn.SetLength(0); - } return result; } @@ -252,6 +247,112 @@ nsDOMCSSDeclaration::SetProperty(const nsAString& aPropertyName, PR_TRUE, PR_FALSE); } +NS_IMETHODIMP +nsDOMCSSDeclaration::RemoveProperty(const nsAString& aPropertyName, + nsAString& aReturn) +{ + aReturn.Truncate(); + + nsCSSDeclaration* decl; + nsresult rv = GetCSSDeclaration(&decl, PR_FALSE); + if (!decl) { + return rv; + } + + nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName); + + decl->GetValue(prop, aReturn); + + rv = decl->RemoveProperty(prop); + + if (NS_SUCCEEDED(rv)) { + rv = DeclarationChanged(); + } else { + // RemoveProperty used to throw in all sorts of situations -- e.g. + // if the property was a shorthand one. Do not propagate its return + // value to callers. (XXX or should we propagate it again now?) + rv = NS_OK; + } + + return rv; +} + +nsresult +nsDOMCSSDeclaration::ParsePropertyValue(const nsAString& aPropName, + const nsAString& aPropValue) +{ + nsCSSDeclaration* decl; + nsresult result = GetCSSDeclaration(&decl, PR_TRUE); + if (!decl) { + return result; + } + + nsCOMPtr cssLoader; + nsCOMPtr cssParser; + nsCOMPtr baseURI; + + result = GetCSSParsingEnvironment(getter_AddRefs(baseURI), + getter_AddRefs(cssLoader), + getter_AddRefs(cssParser)); + if (NS_FAILED(result)) { + return result; + } + + nsChangeHint uselessHint = NS_STYLE_HINT_NONE; + result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, + &uselessHint); + if (NS_SUCCEEDED(result)) { + result = DeclarationChanged(); + } + + if (cssLoader) { + cssLoader->RecycleParser(cssParser); + } + + return result; +} + +nsresult +nsDOMCSSDeclaration::ParseDeclaration(const nsAString& aDecl, + PRBool aParseOnlyOneDecl, + PRBool aClearOldDecl) +{ + nsCSSDeclaration* decl; + nsresult result = GetCSSDeclaration(&decl, PR_TRUE); + if (!decl) { + return result; + } + + nsCOMPtr cssLoader; + nsCOMPtr cssParser; + nsCOMPtr baseURI; + + result = GetCSSParsingEnvironment(getter_AddRefs(baseURI), + getter_AddRefs(cssLoader), + getter_AddRefs(cssParser)); + + if (NS_FAILED(result)) { + return result; + } + + nsChangeHint uselessHint = NS_STYLE_HINT_NONE; + result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, + aParseOnlyOneDecl, + &uselessHint, + aClearOldDecl); + + if (NS_SUCCEEDED(result)) { + result = DeclarationChanged(); + } + + if (cssLoader) { + cssLoader->RecycleParser(cssParser); + } + + return result; +} + + ////////////////////////////////////////////////////////////////////////////// CSS2PropertiesTearoff::CSS2PropertiesTearoff(nsISupports *aOuter) diff --git a/mozilla/content/html/style/src/nsDOMCSSDeclaration.h b/mozilla/content/html/style/src/nsDOMCSSDeclaration.h index 7f0e19e2a05..9421f67683e 100644 --- a/mozilla/content/html/style/src/nsDOMCSSDeclaration.h +++ b/mozilla/content/html/style/src/nsDOMCSSDeclaration.h @@ -47,6 +47,7 @@ class nsCSSDeclaration; class nsICSSParser; +class nsICSSLoader; class nsIURI; class nsDOMCSSDeclaration : public nsIDOMCSSStyleDeclaration @@ -56,35 +57,28 @@ public: NS_DECL_ISUPPORTS - // NS_DECL_IDOMCSSSTYLEDECLARATION - NS_IMETHOD GetCssText(nsAString& aCssText); - NS_IMETHOD SetCssText(const nsAString& aCssText); - NS_IMETHOD GetLength(PRUint32* aLength); - NS_IMETHOD GetParentRule(nsIDOMCSSRule** aParentRule); - NS_IMETHOD GetPropertyValue(const nsAString& aPropertyName, - nsAString& aReturn); - NS_IMETHOD GetPropertyCSSValue(const nsAString& aPropertyName, - nsIDOMCSSValue** aReturn); - NS_IMETHOD RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn) = 0; - NS_IMETHOD GetPropertyPriority(const nsAString& aPropertyName, - nsAString& aReturn); - NS_IMETHOD SetProperty(const nsAString& aPropertyName, - const nsAString& aValue, - const nsAString& aPriority); - NS_IMETHOD Item(PRUint32 aIndex, nsAString& aReturn); - + NS_DECL_NSIDOMCSSSTYLEDECLARATION virtual void DropReference() = 0; - // XXX DeCOMify this, so that |nsCSSDeclaration*| is the return type. +protected: + // Always fills in the out parameter, even on failure, and if the out + // parameter is null the nsresult will be the correct thing to + // propagate. virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate) = 0; - virtual nsresult ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue) = 0; - virtual nsresult ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl) = 0; virtual nsresult GetParent(nsISupports **aParent) = 0; + virtual nsresult DeclarationChanged() = 0; + + // This will only fail if it can't get a parser. This means it can + // return NS_OK without aURI or aCSSLoader being initialized. + virtual nsresult GetCSSParsingEnvironment(nsIURI** aBaseURI, + nsICSSLoader** aCSSLoader, + nsICSSParser** aCSSParser) = 0; + + nsresult ParsePropertyValue(const nsAString& aPropName, + const nsAString& aPropValue); + nsresult ParseDeclaration(const nsAString& aDecl, + PRBool aParseOnlyOneDecl, PRBool aClearOldDecl); protected: virtual ~nsDOMCSSDeclaration(); diff --git a/mozilla/content/html/style/src/nsICSSGroupRule.h b/mozilla/content/html/style/src/nsICSSGroupRule.h index f76a34bb920..210f8287fdc 100644 --- a/mozilla/content/html/style/src/nsICSSGroupRule.h +++ b/mozilla/content/html/style/src/nsICSSGroupRule.h @@ -59,14 +59,13 @@ public: NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const = 0; /* - * The next two methods (DeleteStyleRuleAt and InsertStyleRulesAt) - * should never be called unless you have first called WillDirty() - * on the parent stylesheet. After they are called, DidDirty() - * needs to be called on the sheet + * The next three methods should never be called unless you have first + * called WillDirty() on the parent stylesheet. After they are + * called, DidDirty() needs to be called on the sheet. */ NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex) = 0; NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) = 0; - + NS_IMETHOD ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) = 0; }; diff --git a/mozilla/content/html/style/src/nsICSSStyleRule.h b/mozilla/content/html/style/src/nsICSSStyleRule.h index c19044afac5..94afae748e4 100644 --- a/mozilla/content/html/style/src/nsICSSStyleRule.h +++ b/mozilla/content/html/style/src/nsICSSStyleRule.h @@ -201,7 +201,18 @@ public: virtual void SetLineNumber(PRUint32 aLineNumber) = 0; virtual nsCSSDeclaration* GetDeclaration(void) const = 0; - virtual void SetDeclaration(nsCSSDeclaration* aDeclaration) = 0; + + /** + * Return a new |nsIStyleRule| instance that replaces the current one, + * due to a change in the |nsCSSDeclaration|. Due to the + * |nsIStyleRule| contract of immutability, this must be called if the + * declaration is modified. + * + * |DeclarationChanged| handles replacing the object in the container + * sheet or group rule if |aHandleContainer| is true. + */ + virtual already_AddRefed + DeclarationChanged(PRBool aHandleContainer) = 0; virtual already_AddRefed GetImportantRule(void) = 0; @@ -211,6 +222,7 @@ public: nsresult NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult, - nsCSSSelectorList* aSelector); + nsCSSSelectorList* aSelector, + nsCSSDeclaration* aDeclaration); #endif /* nsICSSStyleRule_h___ */ diff --git a/mozilla/content/shared/public/nsRuleNode.h b/mozilla/content/shared/public/nsRuleNode.h index b5df7848fdd..c2532afc8cb 100644 --- a/mozilla/content/shared/public/nsRuleNode.h +++ b/mozilla/content/shared/public/nsRuleNode.h @@ -410,8 +410,7 @@ protected: const nsStyleStruct* WalkRuleTree(const nsStyleStructID aSID, nsStyleContext* aContext, nsRuleData* aRuleData, - nsRuleDataStruct* aSpecificData, - PRBool aComputeData); + nsRuleDataStruct* aSpecificData); const nsStyleStruct* ComputeDisplayData(nsStyleStruct* aStartDisplay, const nsRuleDataStruct& aDisplayData, nsStyleContext* aContext, nsRuleNode* aHighestNode, @@ -504,31 +503,31 @@ protected: inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID, const nsRuleDataStruct& aRuleDataStruct); const nsStyleStruct* GetParentData(const nsStyleStructID aSID); - const nsStyleStruct* GetDisplayData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetVisibilityData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetFontData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetColorData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetBackgroundData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetMarginData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetBorderData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetPaddingData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetOutlineData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetListData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetPositionData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetTableData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetTableBorderData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetContentData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetQuotesData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetTextData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetTextResetData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetUserInterfaceData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetUIResetData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetXULData(nsStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetDisplayData(nsStyleContext* aContext); + const nsStyleStruct* GetVisibilityData(nsStyleContext* aContext); + const nsStyleStruct* GetFontData(nsStyleContext* aContext); + const nsStyleStruct* GetColorData(nsStyleContext* aContext); + const nsStyleStruct* GetBackgroundData(nsStyleContext* aContext); + const nsStyleStruct* GetMarginData(nsStyleContext* aContext); + const nsStyleStruct* GetBorderData(nsStyleContext* aContext); + const nsStyleStruct* GetPaddingData(nsStyleContext* aContext); + const nsStyleStruct* GetOutlineData(nsStyleContext* aContext); + const nsStyleStruct* GetListData(nsStyleContext* aContext); + const nsStyleStruct* GetPositionData(nsStyleContext* aContext); + const nsStyleStruct* GetTableData(nsStyleContext* aContext); + const nsStyleStruct* GetTableBorderData(nsStyleContext* aContext); + const nsStyleStruct* GetContentData(nsStyleContext* aContext); + const nsStyleStruct* GetQuotesData(nsStyleContext* aContext); + const nsStyleStruct* GetTextData(nsStyleContext* aContext); + const nsStyleStruct* GetTextResetData(nsStyleContext* aContext); + const nsStyleStruct* GetUserInterfaceData(nsStyleContext* aContext); + const nsStyleStruct* GetUIResetData(nsStyleContext* aContext); + const nsStyleStruct* GetXULData(nsStyleContext* aContext); #ifdef MOZ_SVG - const nsStyleStruct* GetSVGData(nsStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetSVGData(nsStyleContext* aContext); #endif - typedef const nsStyleStruct* (nsRuleNode::*GetStyleDataFn)(nsStyleContext*, PRBool); + typedef const nsStyleStruct* (nsRuleNode::*GetStyleDataFn)(nsStyleContext*); static GetStyleDataFn gGetStyleDataFn[]; public: @@ -557,8 +556,7 @@ public: return mPresContext; } - nsresult ClearCachedData(nsIStyleRule* aRule); - nsresult ClearCachedDataInSubtree(nsIStyleRule* aRule); + nsresult ClearStyleData(); nsresult GetPresContext(nsIPresContext** aResult); nsresult PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched); const nsStyleStruct* GetStyleData(nsStyleStructID aSID, diff --git a/mozilla/content/shared/public/nsStyleContext.h b/mozilla/content/shared/public/nsStyleContext.h index 1f480293632..be3629234e8 100644 --- a/mozilla/content/shared/public/nsStyleContext.h +++ b/mozilla/content/shared/public/nsStyleContext.h @@ -139,7 +139,7 @@ public: nsStyleStruct* GetUniqueStyleData(nsIPresContext* aPresContext, const nsStyleStructID& aSID); - void ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule); + void ClearStyleData(nsIPresContext* aPresContext); nsChangeHint CalcStyleDifference(nsStyleContext* aOther); diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 4c283a2f3b7..c7dcf639adc 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -10553,78 +10553,6 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, return result; } - // Style change notifications -NS_IMETHODIMP -nsCSSFrameConstructor::StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) -{ - nsresult result = NS_OK; - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - nsIFrame* frame; - shell->GetRootFrame(&frame); - - if (!frame) { - return NS_OK; - } - - PRBool reframe = (aHint & (nsChangeHint_ReconstructDoc | nsChangeHint_ReconstructFrame - | nsChangeHint_Unknown)) != 0; - PRBool restyle = (aHint & ~(nsChangeHint_AttrChange)) != 0; - // TBD: add "review" to update view? - - if (restyle) { - nsCOMPtr set; - shell->GetStyleSet(getter_AddRefs(set)); - set->ClearStyleData(aPresContext, aStyleRule); - } - - if (reframe) { - result = ReconstructDocElementHierarchy(aPresContext); - } - else { - PRBool reflow = (aHint & (nsChangeHint_ReconstructDoc | nsChangeHint_ReconstructFrame - | nsChangeHint_ReflowFrame | nsChangeHint_Unknown)) != 0; - PRBool renderOrSync = (aHint & (nsChangeHint_ReconstructDoc | nsChangeHint_ReconstructFrame - | nsChangeHint_ReflowFrame | nsChangeHint_RepaintFrame - | nsChangeHint_Unknown | nsChangeHint_SyncFrameView)) != 0; - - // XXX hack, skip the root and scrolling frames - frame->FirstChild(aPresContext, nsnull, &frame); - frame->FirstChild(aPresContext, nsnull, &frame); - if (reflow) { - StyleChangeReflow(aPresContext, frame, nsnull); - } - if (renderOrSync) { - ApplyRenderingChangeToTree(aPresContext, frame, nsnull, aHint); - } - } - - return result; -} - -NS_IMETHODIMP -nsCSSFrameConstructor::StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) -{ - // XXX TBI: should query rule for impact and do minimal work - ReconstructDocElementHierarchy(aPresContext); - return NS_OK; -} - -NS_IMETHODIMP -nsCSSFrameConstructor::StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) -{ - // XXX TBI: should query rule for impact and do minimal work - ReconstructDocElementHierarchy(aPresContext); - return NS_OK; -} - //STATIC void nsCSSFrameConstructor::GetAlternateTextFor(nsIContent* aContent, nsIAtom* aTag, // content object's tag diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index ef3c7aa26c2..eedc0488573 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -141,20 +141,6 @@ public: PRInt32 aModType, nsChangeHint aHint); - // Style change notifications - NS_IMETHOD StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint); - - NS_IMETHOD StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - - NS_IMETHOD StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - NS_IMETHOD ProcessRestyledFrames(nsStyleChangeList& aRestyleArray, nsIPresContext* aPresContext); diff --git a/mozilla/layout/base/nsPresContext.cpp b/mozilla/layout/base/nsPresContext.cpp index 0579fda8ab8..e49206ef765 100644 --- a/mozilla/layout/base/nsPresContext.cpp +++ b/mozilla/layout/base/nsPresContext.cpp @@ -576,7 +576,7 @@ nsPresContext::ClearStyleDataAndReflow() // Clear out all our style data. nsCOMPtr set; mShell->GetStyleSet(getter_AddRefs(set)); - set->ClearStyleData(this, nsnull); + set->ClearStyleData(this); // Force a reflow of the root frame // XXX We really should only do a reflow if a preference that affects diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index ed8be251411..0d99dec0e0f 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -5657,15 +5657,10 @@ PresShell::StyleSheetApplicableStateChanged(nsIDocument *aDocument, NS_IMETHODIMP PresShell::StyleRuleChanged(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) + nsIStyleRule* aOldStyleRule, + nsIStyleRule* aNewStyleRule) { - WillCauseReflow(); - nsresult rv = mStyleSet->StyleRuleChanged(mPresContext, aStyleSheet, - aStyleRule, aHint); - VERIFY_STYLE_TREE; - DidCauseReflow(); - return rv; + return ReconstructStyleData(PR_FALSE); } NS_IMETHODIMP @@ -5673,18 +5668,6 @@ PresShell::StyleRuleAdded(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) { - WillCauseReflow(); - nsresult rv = mStyleSet->StyleRuleAdded(mPresContext, aStyleSheet, - aStyleRule); - VERIFY_STYLE_TREE; - DidCauseReflow(); - if (NS_FAILED(rv)) { - return rv; - } - - // We don't need to rebuild the - // rule tree, since no rule nodes have been rendered invalid by the - // addition of new rule content. return ReconstructStyleData(PR_FALSE); } @@ -5693,16 +5676,7 @@ PresShell::StyleRuleRemoved(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) { - WillCauseReflow(); - nsresult rv = mStyleSet->StyleRuleRemoved(mPresContext, aStyleSheet, - aStyleRule); - VERIFY_STYLE_TREE; - DidCauseReflow(); - if (NS_FAILED(rv)) { - return rv; - } - // XXX For now reconstruct everything - return ReconstructFrames(); + return ReconstructStyleData(PR_FALSE); } NS_IMETHODIMP @@ -5796,7 +5770,7 @@ PresShell::BidiStyleChangeReflow() nsIFrame* rootFrame; mFrameManager->GetRootFrame(&rootFrame); if (rootFrame) { - mStyleSet->ClearStyleData(mPresContext, nsnull); + mStyleSet->ClearStyleData(mPresContext); ReconstructFrames(); } return NS_OK; diff --git a/mozilla/layout/base/public/nsIStyleFrameConstruction.h b/mozilla/layout/base/public/nsIStyleFrameConstruction.h index 2bc330c6b8b..bdc1c84e3c9 100644 --- a/mozilla/layout/base/public/nsIStyleFrameConstruction.h +++ b/mozilla/layout/base/public/nsIStyleFrameConstruction.h @@ -233,61 +233,6 @@ public: nsChangeHint aHint) = 0; - /////////////// Style change notifications ////////////////// - - /** - * A StyleRule has just been modified within a style sheet. - * - * @param aDocument The document being observed - * @param aStyleSheet the StyleSheet that contians the rule - * @param aStyleRule the rule that was modified - * @param aHint some possible info about the nature of the change. - * see nsStyleConsts for hint values - * - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) = 0; // See nsStyleConsts fot hint values - - /** - * A StyleRule has just been added to a style sheet. - * This method is called automatically when the rule gets - * added to the sheet. The style sheet passes this - * notification to the document. The notification is passed on - * to all of the document observers. - * - * @param aDocument The document being observed - * @param aStyleSheet the StyleSheet that has been modified - * @param aStyleRule the rule that was added - * - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) = 0; - - /** - * A StyleRule has just been removed from a style sheet. - * This method is called automatically when the rule gets - * removed from the sheet. The style sheet passes this - * notification to the document. The notification is passed on - * to all of the document observers. - * - * @param aDocument The document being observed - * @param aStyleSheet the StyleSheet that has been modified - * @param aStyleRule the rule that was removed - * - * @return NS_OK - * @see nsIDocumentObserver - */ - NS_IMETHOD StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) = 0; - /** * Method that actually handles style changes for effected frames. * Note: this may not need to be a public method. Use with extreme caution. diff --git a/mozilla/layout/base/public/nsIStyleSet.h b/mozilla/layout/base/public/nsIStyleSet.h index 5a4025ad5c1..e237934b263 100644 --- a/mozilla/layout/base/public/nsIStyleSet.h +++ b/mozilla/layout/base/public/nsIStyleSet.h @@ -131,13 +131,8 @@ public: virtual nsresult GetStyleFrameConstruction(nsIStyleFrameConstruction** aResult) = 0; - // ClearCachedStyleData is used to invalidate portions of both the style context tree - // and rule tree without destroying the actual nodes in the two trees. |aRule| provides - // a hint as to which rule has changed, and all subtree data pruning will occur rooted - // only on style contexts and rule nodes that use that rule. If the rule is null, then - // it is assumed that both trees are to be entirely wiped. - // - virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule) = 0; + // Clear all style data cached in the style context tree and rule tree. + virtual nsresult ClearStyleData(nsIPresContext* aPresContext) = 0; // enable / disable the Quirk style sheet: // returns NS_FAILURE if none is found, otherwise NS_OK @@ -253,18 +248,6 @@ public: PRInt32 aModType, nsChangeHint aHint) = 0; - // Style change notifications - NS_IMETHOD StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) = 0; - NS_IMETHOD StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) = 0; - NS_IMETHOD StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) = 0; - // Notification that we were unable to render a replaced element. // Called when the replaced element can not be rendered, and we should // instead render the element's contents. diff --git a/mozilla/layout/base/src/nsPresContext.cpp b/mozilla/layout/base/src/nsPresContext.cpp index 0579fda8ab8..e49206ef765 100644 --- a/mozilla/layout/base/src/nsPresContext.cpp +++ b/mozilla/layout/base/src/nsPresContext.cpp @@ -576,7 +576,7 @@ nsPresContext::ClearStyleDataAndReflow() // Clear out all our style data. nsCOMPtr set; mShell->GetStyleSet(getter_AddRefs(set)); - set->ClearStyleData(this, nsnull); + set->ClearStyleData(this); // Force a reflow of the root frame // XXX We really should only do a reflow if a preference that affects diff --git a/mozilla/layout/html/base/src/nsPresShell.cpp b/mozilla/layout/html/base/src/nsPresShell.cpp index ed8be251411..0d99dec0e0f 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -5657,15 +5657,10 @@ PresShell::StyleSheetApplicableStateChanged(nsIDocument *aDocument, NS_IMETHODIMP PresShell::StyleRuleChanged(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) + nsIStyleRule* aOldStyleRule, + nsIStyleRule* aNewStyleRule) { - WillCauseReflow(); - nsresult rv = mStyleSet->StyleRuleChanged(mPresContext, aStyleSheet, - aStyleRule, aHint); - VERIFY_STYLE_TREE; - DidCauseReflow(); - return rv; + return ReconstructStyleData(PR_FALSE); } NS_IMETHODIMP @@ -5673,18 +5668,6 @@ PresShell::StyleRuleAdded(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) { - WillCauseReflow(); - nsresult rv = mStyleSet->StyleRuleAdded(mPresContext, aStyleSheet, - aStyleRule); - VERIFY_STYLE_TREE; - DidCauseReflow(); - if (NS_FAILED(rv)) { - return rv; - } - - // We don't need to rebuild the - // rule tree, since no rule nodes have been rendered invalid by the - // addition of new rule content. return ReconstructStyleData(PR_FALSE); } @@ -5693,16 +5676,7 @@ PresShell::StyleRuleRemoved(nsIDocument *aDocument, nsIStyleSheet* aStyleSheet, nsIStyleRule* aStyleRule) { - WillCauseReflow(); - nsresult rv = mStyleSet->StyleRuleRemoved(mPresContext, aStyleSheet, - aStyleRule); - VERIFY_STYLE_TREE; - DidCauseReflow(); - if (NS_FAILED(rv)) { - return rv; - } - // XXX For now reconstruct everything - return ReconstructFrames(); + return ReconstructStyleData(PR_FALSE); } NS_IMETHODIMP @@ -5796,7 +5770,7 @@ PresShell::BidiStyleChangeReflow() nsIFrame* rootFrame; mFrameManager->GetRootFrame(&rootFrame); if (rootFrame) { - mStyleSet->ClearStyleData(mPresContext, nsnull); + mStyleSet->ClearStyleData(mPresContext); ReconstructFrames(); } return NS_OK; diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 4c283a2f3b7..c7dcf639adc 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -10553,78 +10553,6 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, return result; } - // Style change notifications -NS_IMETHODIMP -nsCSSFrameConstructor::StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) -{ - nsresult result = NS_OK; - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - nsIFrame* frame; - shell->GetRootFrame(&frame); - - if (!frame) { - return NS_OK; - } - - PRBool reframe = (aHint & (nsChangeHint_ReconstructDoc | nsChangeHint_ReconstructFrame - | nsChangeHint_Unknown)) != 0; - PRBool restyle = (aHint & ~(nsChangeHint_AttrChange)) != 0; - // TBD: add "review" to update view? - - if (restyle) { - nsCOMPtr set; - shell->GetStyleSet(getter_AddRefs(set)); - set->ClearStyleData(aPresContext, aStyleRule); - } - - if (reframe) { - result = ReconstructDocElementHierarchy(aPresContext); - } - else { - PRBool reflow = (aHint & (nsChangeHint_ReconstructDoc | nsChangeHint_ReconstructFrame - | nsChangeHint_ReflowFrame | nsChangeHint_Unknown)) != 0; - PRBool renderOrSync = (aHint & (nsChangeHint_ReconstructDoc | nsChangeHint_ReconstructFrame - | nsChangeHint_ReflowFrame | nsChangeHint_RepaintFrame - | nsChangeHint_Unknown | nsChangeHint_SyncFrameView)) != 0; - - // XXX hack, skip the root and scrolling frames - frame->FirstChild(aPresContext, nsnull, &frame); - frame->FirstChild(aPresContext, nsnull, &frame); - if (reflow) { - StyleChangeReflow(aPresContext, frame, nsnull); - } - if (renderOrSync) { - ApplyRenderingChangeToTree(aPresContext, frame, nsnull, aHint); - } - } - - return result; -} - -NS_IMETHODIMP -nsCSSFrameConstructor::StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) -{ - // XXX TBI: should query rule for impact and do minimal work - ReconstructDocElementHierarchy(aPresContext); - return NS_OK; -} - -NS_IMETHODIMP -nsCSSFrameConstructor::StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) -{ - // XXX TBI: should query rule for impact and do minimal work - ReconstructDocElementHierarchy(aPresContext); - return NS_OK; -} - //STATIC void nsCSSFrameConstructor::GetAlternateTextFor(nsIContent* aContent, nsIAtom* aTag, // content object's tag diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h index ef3c7aa26c2..eedc0488573 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h @@ -141,20 +141,6 @@ public: PRInt32 aModType, nsChangeHint aHint); - // Style change notifications - NS_IMETHOD StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint); - - NS_IMETHOD StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - - NS_IMETHOD StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - NS_IMETHOD ProcessRestyledFrames(nsStyleChangeList& aRestyleArray, nsIPresContext* aPresContext); diff --git a/mozilla/layout/style/nsCSSParser.cpp b/mozilla/layout/style/nsCSSParser.cpp index b248ffea8a2..e52cb771735 100644 --- a/mozilla/layout/style/nsCSSParser.cpp +++ b/mozilla/layout/style/nsCSSParser.cpp @@ -640,12 +640,11 @@ CSSParserImpl::ParseStyleAttribute(const nsAString& aAttributeValue, if (declaration) { // Create a style rule for the delcaration nsICSSStyleRule* rule = nsnull; - rv = NS_NewCSSStyleRule(&rule, nsnull); + rv = NS_NewCSSStyleRule(&rule, nsnull, declaration); if (NS_FAILED(rv)) { declaration->RuleAbort(); return rv; } - rule->SetDeclaration(declaration); *aResult = rule; } else { @@ -1473,14 +1472,13 @@ PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode, RuleAppendFunc aAppendFu // Translate the selector list and declaration block into style data nsCOMPtr rule; - NS_NewCSSStyleRule(getter_AddRefs(rule), slist); + NS_NewCSSStyleRule(getter_AddRefs(rule), slist, declaration); if (!rule) { aErrorCode = NS_ERROR_OUT_OF_MEMORY; delete slist; return PR_FALSE; } rule->SetLineNumber(linenum); - rule->SetDeclaration(declaration); (*aAppendFunc)(rule, aData); return PR_TRUE; diff --git a/mozilla/layout/style/nsCSSRules.cpp b/mozilla/layout/style/nsCSSRules.cpp index aed43a7e994..a70066583fe 100644 --- a/mozilla/layout/style/nsCSSRules.cpp +++ b/mozilla/layout/style/nsCSSRules.cpp @@ -662,6 +662,7 @@ public: NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const; NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex); NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules); + NS_IMETHOD ReplaceStyleRule(nsICSSRule *aOld, nsICSSRule *aNew); // nsIDOMCSSRule interface NS_DECL_NSIDOMCSSRULE @@ -872,6 +873,8 @@ CSSMediaRuleImpl::AppendStyleRule(nsICSSRule* aRule) aRule->SetStyleSheet(mSheet); aRule->SetParentRule(this); if (mSheet) { + // XXXldb Shouldn't we be using |WillDirty| and |DidDirty| (and + // shouldn't |SetModified| be removed? mSheet->SetModified(PR_TRUE); } } @@ -952,6 +955,18 @@ CSSMediaRuleImpl::InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) return NS_OK; } +NS_IMETHODIMP +CSSMediaRuleImpl::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) +{ + PRInt32 index = mRules->IndexOf(aOld); + NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); + mRules->ReplaceElementAt(aNew, index); + aNew->SetStyleSheet(mSheet); + aNew->SetParentRule(this); + aOld->SetStyleSheet(nsnull); + aOld->SetParentRule(nsnull); + return NS_OK; +} nsresult NS_NewCSSMediaRule(nsICSSMediaRule** aInstancePtrResult) diff --git a/mozilla/layout/style/nsCSSStyleRule.cpp b/mozilla/layout/style/nsCSSStyleRule.cpp index e72cabd41df..b428220ca60 100644 --- a/mozilla/layout/style/nsCSSStyleRule.cpp +++ b/mozilla/layout/style/nsCSSStyleRule.cpp @@ -854,7 +854,7 @@ CSSImportantRule::List(FILE* out, PRInt32 aIndent) const } #endif -// -- nsDOMStyleRuleDeclaration ------------------------------- +// -- DOMCSSDeclarationImpl ------------------------------- class DOMCSSDeclarationImpl : public nsDOMCSSDeclaration { @@ -862,24 +862,14 @@ public: DOMCSSDeclarationImpl(nsICSSStyleRule *aRule); ~DOMCSSDeclarationImpl(void); - NS_IMETHOD RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn); - virtual void DropReference(void); virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate); - virtual nsresult GetCSSParsingEnvironment(nsICSSStyleRule* aRule, - nsICSSStyleSheet** aSheet, - nsIDocument** aDocument, - nsIURI** aURI, + virtual nsresult GetCSSParsingEnvironment(nsIURI** aURI, nsICSSLoader** aCSSLoader, nsICSSParser** aCSSParser); - virtual nsresult ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue); - virtual nsresult ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl); virtual nsresult GetParent(nsISupports **aParent); + virtual nsresult DeclarationChanged(); protected: nsICSSStyleRule *mRule; @@ -901,55 +891,6 @@ DOMCSSDeclarationImpl::~DOMCSSDeclarationImpl(void) MOZ_COUNT_DTOR(DOMCSSDeclarationImpl); } -NS_IMETHODIMP -DOMCSSDeclarationImpl::RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn) -{ - aReturn.Truncate(); - - nsCSSDeclaration* decl; - nsresult rv = GetCSSDeclaration(&decl, PR_TRUE); - - if (NS_SUCCEEDED(rv) && decl) { - nsCOMPtr cssSheet; - nsCOMPtr owningDoc; - if (mRule) { - nsCOMPtr sheet; - mRule->GetStyleSheet(*getter_AddRefs(sheet)); - cssSheet = do_QueryInterface(sheet); - if (sheet) { - sheet->GetOwningDocument(*getter_AddRefs(owningDoc)); - } - } - if (owningDoc) { - owningDoc->BeginUpdate(); - } - nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName); - - decl->GetValue(prop, aReturn); - - rv = decl->RemoveProperty(prop); - - if (NS_SUCCEEDED(rv)) { - if (cssSheet) { - cssSheet->SetModified(PR_TRUE); - } - if (owningDoc) { - owningDoc->StyleRuleChanged(cssSheet, mRule, nsCSSProps::kHintTable[prop]); - } - } else { - // If we tried to remove an invalid property or a property that wasn't - // set we simply return success and an empty string - rv = NS_OK; - } - if (owningDoc) { - owningDoc->EndUpdate(); - } - } - - return rv; -} - void DOMCSSDeclarationImpl::DropReference(void) { @@ -972,38 +913,34 @@ DOMCSSDeclarationImpl::GetCSSDeclaration(nsCSSDeclaration **aDecl, /* * This is a utility function. It will only fail if it can't get a - * parser. This means it can return NS_OK without all of aSheet, - * aDocument, aURI, aCSSLoader being initialized + * parser. This means it can return NS_OK without aURI or aCSSLoader + * being initialized. */ nsresult -DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsICSSStyleRule* aRule, - nsICSSStyleSheet** aSheet, - nsIDocument** aDocument, - nsIURI** aURI, +DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsIURI** aURI, nsICSSLoader** aCSSLoader, nsICSSParser** aCSSParser) { // null out the out params since some of them may not get initialized below - *aSheet = nsnull; - *aDocument = nsnull; *aURI = nsnull; *aCSSLoader = nsnull; *aCSSParser = nsnull; nsresult result; nsCOMPtr sheet; - if (aRule) { - aRule->GetStyleSheet(*getter_AddRefs(sheet)); + if (mRule) { + mRule->GetStyleSheet(*getter_AddRefs(sheet)); if (sheet) { - CallQueryInterface(sheet, aSheet); - sheet->GetOwningDocument(*aDocument); sheet->GetURL(*aURI); + nsCOMPtr document; + sheet->GetOwningDocument(*getter_AddRefs(document)); + nsCOMPtr htmlContainer = + do_QueryInterface(document); + if (htmlContainer) { + htmlContainer->GetCSSLoader(*aCSSLoader); + NS_ASSERTION(*aCSSLoader, "Document with no CSS loader!"); + } } } - nsCOMPtr htmlContainer(do_QueryInterface(*aDocument)); - if (htmlContainer) { - htmlContainer->GetCSSLoader(*aCSSLoader); - } - NS_ASSERTION(*aCSSLoader || !*aDocument, "Document with no CSS loader!"); if (*aCSSLoader) { result = (*aCSSLoader)->GetParserFor(nsnull, aCSSParser); } else { @@ -1013,99 +950,6 @@ DOMCSSDeclarationImpl::GetCSSParsingEnvironment(nsICSSStyleRule* aRule, return result; } -nsresult -DOMCSSDeclarationImpl::ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue) -{ - nsCSSDeclaration* decl; - nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - if (!decl) { - return result; - } - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - nsCOMPtr cssSheet; - nsCOMPtr owningDoc; - result = GetCSSParsingEnvironment(mRule, - getter_AddRefs(cssSheet), - getter_AddRefs(owningDoc), - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - - if (NS_FAILED(result)) { - return result; - } - - nsChangeHint hint; - if (owningDoc) { - owningDoc->BeginUpdate(); - } - result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, &hint); - if (NS_SUCCEEDED(result)) { - if (cssSheet) { - cssSheet->SetModified(PR_TRUE); - } - if (owningDoc) { - owningDoc->StyleRuleChanged(cssSheet, mRule, hint); - owningDoc->EndUpdate(); - } - } - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - - return result; -} - -nsresult -DOMCSSDeclarationImpl::ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl) -{ - nsCSSDeclaration* decl; - nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - - if (decl) { - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - nsCOMPtr cssSheet; - nsCOMPtr owningDoc; - - result = GetCSSParsingEnvironment(mRule, - getter_AddRefs(cssSheet), - getter_AddRefs(owningDoc), - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - - if (NS_SUCCEEDED(result)) { - nsChangeHint hint; - result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, - aParseOnlyOneDecl, &hint, - aClearOldDecl); - - if (NS_SUCCEEDED(result)) { - if (cssSheet) { - cssSheet->SetModified(PR_TRUE); - } - if (owningDoc) { - owningDoc->StyleRuleChanged(cssSheet, mRule, hint); - } - } - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - } - } - - return result; -} - - - nsresult DOMCSSDeclarationImpl::GetParent(nsISupports **aParent) { @@ -1120,6 +964,37 @@ DOMCSSDeclarationImpl::GetParent(nsISupports **aParent) return NS_OK; } +nsresult +DOMCSSDeclarationImpl::DeclarationChanged() +{ + NS_PRECONDITION(mRule, + "can only be called when |GetCSSDeclaration| returned a declaration"); + + nsCOMPtr owningDoc; + nsCOMPtr sheet; + mRule->GetStyleSheet(*getter_AddRefs(sheet)); + if (sheet) { + sheet->GetOwningDocument(*getter_AddRefs(owningDoc)); + } + + if (owningDoc) { + // XXXldb Do we need to bother with this? We're now doing it in + // more places than we used to, but it probably doesn't matter... + owningDoc->BeginUpdate(); + } + + nsCOMPtr oldRule = mRule; + mRule = oldRule->DeclarationChanged(PR_TRUE).get(); + nsrefcnt cnt = mRule->Release(); + NS_ASSERTION(cnt != 0, "container didn't take ownership"); + + if (owningDoc) { + owningDoc->StyleRuleChanged(sheet, oldRule, mRule); + owningDoc->EndUpdate(); + } + return NS_OK; +} + // -- nsCSSStyleRule ------------------------------- class CSSStyleRuleImpl : public nsCSSRule, @@ -1127,8 +1002,15 @@ class CSSStyleRuleImpl : public nsCSSRule, public nsIDOMCSSStyleRule { public: - CSSStyleRuleImpl(nsCSSSelectorList* aSelector); + CSSStyleRuleImpl(nsCSSSelectorList* aSelector, + nsCSSDeclaration *aDeclaration); +private: + // for |Clone| CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy); + // for |DeclarationChanged| + CSSStyleRuleImpl(CSSStyleRuleImpl& aCopy, + nsCSSDeclaration *aDeclaration); +public: NS_DECL_ISUPPORTS_INHERITED @@ -1138,7 +1020,6 @@ public: virtual void SetLineNumber(PRUint32 aLineNumber); virtual nsCSSDeclaration* GetDeclaration(void) const; - virtual void SetDeclaration(nsCSSDeclaration* aDeclaration); virtual already_AddRefed GetImportantRule(void); @@ -1153,6 +1034,9 @@ public: NS_IMETHOD GetType(PRInt32& aType) const; NS_IMETHOD Clone(nsICSSRule*& aClone) const; + virtual already_AddRefed + DeclarationChanged(PRBool aHandleContainer); + // The new mapping function. NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData); @@ -1181,30 +1065,50 @@ protected: PRUint32 mLineNumber; }; -CSSStyleRuleImpl::CSSStyleRuleImpl(nsCSSSelectorList* aSelector) +CSSStyleRuleImpl::CSSStyleRuleImpl(nsCSSSelectorList* aSelector, + nsCSSDeclaration* aDeclaration) : nsCSSRule(), - mSelector(aSelector), mDeclaration(nsnull), + mSelector(aSelector), + mDeclaration(aDeclaration), mImportantRule(nsnull), mDOMDeclaration(nsnull) { + if (mDeclaration) + mDeclaration->AddRef(); } +// for |Clone| CSSStyleRuleImpl::CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy) : nsCSSRule(aCopy), mSelector(aCopy.mSelector ? aCopy.mSelector->Clone() : nsnull), - mDeclaration(nsnull), + mDeclaration(aCopy.mDeclaration ? aCopy.mDeclaration->Clone() : nsnull), mImportantRule(nsnull), mDOMDeclaration(nsnull) { - if (aCopy.mDeclaration) { - mDeclaration = aCopy.mDeclaration->Clone(); - if (nsnull != mDeclaration) { - mDeclaration->AddRef(); - } - } + if (mDeclaration) + mDeclaration->AddRef(); // rest is constructed lazily on existing data } +// for |DeclarationChanged| +CSSStyleRuleImpl::CSSStyleRuleImpl(CSSStyleRuleImpl& aCopy, + nsCSSDeclaration* aDeclaration) + : nsCSSRule(aCopy), + mSelector(aCopy.mSelector), + mDeclaration(aDeclaration), + mImportantRule(nsnull), + mDOMDeclaration(aCopy.mDOMDeclaration) +{ + // The DOM declaration is replacing |aCopy| with |this|, so transfer + // the reverse pointer as well. + aCopy.mDOMDeclaration = nsnull; + + // Transfer ownership of selector and declaration: + NS_ASSERTION(aDeclaration == aCopy.mDeclaration, "declaration mismatch"); + aCopy.mSelector = nsnull; + aCopy.mDeclaration = nsnull; +} + CSSStyleRuleImpl::~CSSStyleRuleImpl(void) { @@ -1259,20 +1163,7 @@ void CSSStyleRuleImpl::SetLineNumber(PRUint32 aLineNumber) nsCSSDeclaration* CSSStyleRuleImpl::GetDeclaration(void) const { - nsCSSDeclaration* result = mDeclaration; - return result; -} - -void CSSStyleRuleImpl::SetDeclaration(nsCSSDeclaration* aDeclaration) -{ - if (mDeclaration != aDeclaration) { - NS_IF_RELEASE(mImportantRule); - if (nsnull != mDeclaration) { - mDeclaration->Release(); - } - mDeclaration = aDeclaration; - mDeclaration->AddRef(); - } + return mDeclaration; } already_AddRefed CSSStyleRuleImpl::GetImportantRule(void) @@ -1326,11 +1217,32 @@ NS_IMETHODIMP CSSStyleRuleImpl::Clone(nsICSSRule*& aClone) const { CSSStyleRuleImpl* clone = new CSSStyleRuleImpl(*this); - if (clone) { - return CallQueryInterface(clone, &aClone); + if (!clone) { + aClone = nsnull; + return NS_ERROR_OUT_OF_MEMORY; } - aClone = nsnull; - return NS_ERROR_OUT_OF_MEMORY; + return CallQueryInterface(clone, &aClone); +} + +/* virtual */ already_AddRefed +CSSStyleRuleImpl::DeclarationChanged(PRBool aHandleContainer) +{ + CSSStyleRuleImpl* clone = new CSSStyleRuleImpl(*this, mDeclaration); + if (!clone) { + return nsnull; + } + + NS_ADDREF(clone); // for return + + if (aHandleContainer) { + if (mParentRule) { + mSheet->ReplaceRuleInGroup(mParentRule, this, clone); + } else { + mSheet->ReplaceStyleRule(this, clone); + } + } + + return clone; } NS_IMETHODIMP @@ -1457,13 +1369,10 @@ CSSStyleRuleImpl::GetStyle(nsIDOMCSSStyleDeclaration** aStyle) nsresult NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult, - nsCSSSelectorList* aSelector) + nsCSSSelectorList* aSelector, + nsCSSDeclaration* aDeclaration) { - if (aInstancePtrResult == nsnull) { - return NS_ERROR_NULL_POINTER; - } - - CSSStyleRuleImpl *it = new CSSStyleRuleImpl(aSelector); + CSSStyleRuleImpl *it = new CSSStyleRuleImpl(aSelector, aDeclaration); if (!it) { return NS_ERROR_OUT_OF_MEMORY; } diff --git a/mozilla/layout/style/nsCSSStyleSheet.cpp b/mozilla/layout/style/nsCSSStyleSheet.cpp index d93fa334b6b..9fc2ff1945c 100644 --- a/mozilla/layout/style/nsCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsCSSStyleSheet.cpp @@ -819,6 +819,7 @@ public: NS_IMETHOD ClearMedia(void); NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex); NS_IMETHOD InsertRuleIntoGroup(const nsAString& aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval); + NS_IMETHOD ReplaceRuleInGroup(nsICSSGroupRule* aGroup, nsICSSRule* aOld, nsICSSRule* aNew); NS_IMETHOD GetApplicable(PRBool& aApplicable) const; @@ -847,6 +848,7 @@ public: // XXX do these belong here or are they generic? NS_IMETHOD PrependStyleRule(nsICSSRule* aRule); NS_IMETHOD AppendStyleRule(nsICSSRule* aRule); + NS_IMETHOD ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew); NS_IMETHOD StyleRuleCount(PRInt32& aCount) const; NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const; @@ -1354,7 +1356,8 @@ DOMMediaListImpl::EndMediaChange(void) mStyleSheet->DidDirty(); rv = mStyleSheet->GetOwningDocument(*getter_AddRefs(doc)); NS_ENSURE_SUCCESS(rv, rv); - rv = doc->StyleRuleChanged(mStyleSheet, nsnull, NS_STYLE_HINT_RECONSTRUCT_ALL); + // XXXldb Pass something meaningful? + rv = doc->StyleRuleChanged(mStyleSheet, nsnull, nsnull); NS_ENSURE_SUCCESS(rv, rv); rv = doc->EndUpdate(); NS_ENSURE_SUCCESS(rv, rv); @@ -2159,6 +2162,32 @@ CSSStyleSheetImpl::AppendStyleRule(nsICSSRule* aRule) return NS_OK; } +NS_IMETHODIMP +CSSStyleSheetImpl::ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) +{ + NS_PRECONDITION(mInner->mOrderedRules, "can't have old rule"); + NS_PRECONDITION(mInner && mInner->mComplete, + "No replacing in an incomplete sheet!"); + + if (NS_SUCCEEDED(WillDirty())) { + PRInt32 index = mInner->mOrderedRules->IndexOf(aOld); + NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); + mInner->mOrderedRules->ReplaceElementAt(aNew, index); + + aNew->SetStyleSheet(this); + aOld->SetStyleSheet(nsnull); + DidDirty(); +#ifdef DEBUG + PRInt32 type = nsICSSRule::UNKNOWN_RULE; + aNew->GetType(type); + NS_ASSERTION(nsICSSRule::NAMESPACE_RULE != type, "not yet implemented"); + aOld->GetType(type); + NS_ASSERTION(nsICSSRule::NAMESPACE_RULE != type, "not yet implemented"); +#endif + } + return NS_OK; +} + NS_IMETHODIMP CSSStyleSheetImpl::StyleRuleCount(PRInt32& aCount) const { @@ -2981,6 +3010,29 @@ CSSStyleSheetImpl::InsertRuleIntoGroup(const nsAString & aRule, nsICSSGroupRule* return NS_OK; } +NS_IMETHODIMP +CSSStyleSheetImpl::ReplaceRuleInGroup(nsICSSGroupRule* aGroup, + nsICSSRule* aOld, nsICSSRule* aNew) +{ + nsresult result; + NS_PRECONDITION(mInner && mInner->mComplete, + "No replacing in an incomplete sheet!"); +#ifdef DEBUG + { + nsCOMPtr domGroup(do_QueryInterface(aGroup)); + nsCOMPtr groupSheet; + domGroup->GetParentStyleSheet(getter_AddRefs(groupSheet)); + NS_ASSERTION(this == groupSheet, "group doesn't belong to this sheet"); + } +#endif + result = WillDirty(); + NS_ENSURE_SUCCESS(result, result); + + result = aGroup->ReplaceStyleRule(aOld, aNew); + DidDirty(); + return result; +} + // nsICSSLoaderObserver implementation NS_IMETHODIMP CSSStyleSheetImpl::StyleSheetLoaded(nsICSSStyleSheet*aSheet, PRBool aNotify) diff --git a/mozilla/layout/style/nsDOMCSSAttrDeclaration.cpp b/mozilla/layout/style/nsDOMCSSAttrDeclaration.cpp index ddadc3b3ea1..ca1e51a4d7c 100644 --- a/mozilla/layout/style/nsDOMCSSAttrDeclaration.cpp +++ b/mozilla/layout/style/nsDOMCSSAttrDeclaration.cpp @@ -68,35 +68,6 @@ nsDOMCSSAttributeDeclaration::~nsDOMCSSAttributeDeclaration() MOZ_COUNT_DTOR(nsDOMCSSAttributeDeclaration); } -NS_IMETHODIMP -nsDOMCSSAttributeDeclaration::RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn) -{ - aReturn.Truncate(); - - nsCSSDeclaration* decl; - nsresult rv = GetCSSDeclaration(&decl, PR_FALSE); - - if (NS_SUCCEEDED(rv) && decl) { - nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName); - - decl->GetValue(prop, aReturn); - - rv = decl->RemoveProperty(prop); - - if (NS_SUCCEEDED(rv)) { - rv = SetCSSDeclaration(decl, PR_TRUE, PR_TRUE); - } else { - // RemoveProperty will throw in all sorts of situations -- eg if - // the property is a shorthand one. Do not propagate its return - // value to callers. - rv = NS_OK; - } - } - - return rv; -} - void nsDOMCSSAttributeDeclaration::DropReference() { @@ -104,26 +75,25 @@ nsDOMCSSAttributeDeclaration::DropReference() } nsresult -nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration* aDecl, - PRBool aNotify, - PRBool aDeclOwnedByRule) +nsDOMCSSAttributeDeclaration::DeclarationChanged() { NS_ASSERTION(mContent, "Must have content node to set the decl!"); - NS_PRECONDITION(aDecl, "Null decl!"); - - nsCOMPtr cssRule; - nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsnull); - if (NS_FAILED(rv)) { - if (!aDeclOwnedByRule) { - aDecl->RuleAbort(); - } - return rv; + nsHTMLValue val; + nsresult rv = mContent->GetHTMLAttribute(nsHTMLAtoms::style, val); + NS_ASSERTION(rv == NS_CONTENT_ATTR_HAS_VALUE && + eHTMLUnit_ISupports == val.GetUnit(), + "content must have rule"); + nsCOMPtr oldRule = + do_QueryInterface(nsCOMPtr(val.GetISupportsValue())); + + nsCOMPtr newRule = oldRule->DeclarationChanged(PR_FALSE); + if (!newRule) { + return NS_ERROR_OUT_OF_MEMORY; } - cssRule->SetDeclaration(aDecl); return mContent->SetHTMLAttribute(nsHTMLAtoms::style, - nsHTMLValue(cssRule), - aNotify); + nsHTMLValue(newRule), + PR_TRUE); } nsresult @@ -152,7 +122,17 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, decl->RuleAbort(); return NS_ERROR_OUT_OF_MEMORY; } - result = SetCSSDeclaration(decl, PR_FALSE, PR_FALSE); + + nsCOMPtr cssRule; + result = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsnull, decl); + if (NS_FAILED(result)) { + decl->RuleAbort(); + return result; + } + + result = mContent->SetHTMLAttribute(nsHTMLAtoms::style, + nsHTMLValue(cssRule), + PR_FALSE); if (NS_SUCCEEDED(result)) { *aDecl = decl; } @@ -165,22 +145,21 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, /* * This is a utility function. It will only fail if it can't get a * parser. This means it can return NS_OK without aURI or aCSSLoader - * being initialized + * being initialized. */ nsresult -nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIContent* aContent, - nsIURI** aBaseURI, +nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIURI** aBaseURI, nsICSSLoader** aCSSLoader, nsICSSParser** aCSSParser) { - NS_ASSERTION(aContent, "Something is severely broken -- there should be an nsIContent here!"); + NS_ASSERTION(mContent, "Something is severely broken -- there should be an nsIContent here!"); // null out the out params since some of them may not get initialized below *aBaseURI = nsnull; *aCSSLoader = nsnull; *aCSSParser = nsnull; nsCOMPtr nodeInfo; - nsresult result = aContent->GetNodeInfo(getter_AddRefs(nodeInfo)); + nsresult result = mContent->GetNodeInfo(getter_AddRefs(nodeInfo)); if (NS_FAILED(result)) { return result; } @@ -214,85 +193,6 @@ nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(nsIContent* aContent, return NS_OK; } -nsresult -nsDOMCSSAttributeDeclaration::ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue) -{ - nsCSSDeclaration* decl; - nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - - if (!decl) { - return result; - } - - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - - result = GetCSSParsingEnvironment(mContent, - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - if (NS_FAILED(result)) { - return result; - } - - nsChangeHint uselessHint = NS_STYLE_HINT_NONE; - result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, - &uselessHint); - if (NS_SUCCEEDED(result)) { - result = SetCSSDeclaration(decl, PR_TRUE, PR_TRUE); - } - - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - - return result; -} - -nsresult -nsDOMCSSAttributeDeclaration::ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl) -{ - nsCSSDeclaration* decl; - nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - - if (!decl) { - return result; - } - - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - - result = GetCSSParsingEnvironment(mContent, - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - - if (NS_FAILED(result)) { - return result; - } - - nsChangeHint uselessHint = NS_STYLE_HINT_NONE; - result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, - aParseOnlyOneDecl, - &uselessHint, - aClearOldDecl); - - if (NS_SUCCEEDED(result)) { - result = SetCSSDeclaration(decl, PR_TRUE, PR_TRUE); - } - - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - - return result; -} - nsresult nsDOMCSSAttributeDeclaration::GetParent(nsISupports **aParent) { diff --git a/mozilla/layout/style/nsDOMCSSAttrDeclaration.h b/mozilla/layout/style/nsDOMCSSAttrDeclaration.h index 1d2abb93c0e..97575e4e098 100644 --- a/mozilla/layout/style/nsDOMCSSAttrDeclaration.h +++ b/mozilla/layout/style/nsDOMCSSAttrDeclaration.h @@ -55,28 +55,18 @@ public: nsDOMCSSAttributeDeclaration(nsIHTMLContent *aContent); ~nsDOMCSSAttributeDeclaration(); - NS_IMETHOD RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn); - virtual void DropReference(); // If GetCSSDeclaration returns non-null, then the decl it returns // is owned by our current style rule. virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate); - virtual nsresult GetCSSParsingEnvironment(nsIContent* aContent, - nsIURI** aBaseURI, + virtual nsresult GetCSSParsingEnvironment(nsIURI** aBaseURI, nsICSSLoader** aCSSLoader, nsICSSParser** aCSSParser); - virtual nsresult ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue); - virtual nsresult ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl); virtual nsresult GetParent(nsISupports **aParent); protected: - nsresult SetCSSDeclaration(nsCSSDeclaration* aDecl, PRBool aNotify, - PRBool aDeclOwnedByRule); + virtual nsresult DeclarationChanged(); nsIHTMLContent *mContent; }; diff --git a/mozilla/layout/style/nsDOMCSSDeclaration.cpp b/mozilla/layout/style/nsDOMCSSDeclaration.cpp index 7f7f861b7f2..4ccba2920e5 100644 --- a/mozilla/layout/style/nsDOMCSSDeclaration.cpp +++ b/mozilla/layout/style/nsDOMCSSDeclaration.cpp @@ -39,6 +39,7 @@ #include "nsDOMCSSDeclaration.h" #include "nsIDOMCSSRule.h" #include "nsICSSParser.h" +#include "nsICSSLoader.h" #include "nsIStyleRule.h" #include "nsCSSDeclaration.h" #include "nsCSSProps.h" @@ -138,9 +139,10 @@ nsDOMCSSDeclaration::GetLength(PRUint32* aLength) nsCSSDeclaration *decl; nsresult result = GetCSSDeclaration(&decl, PR_FALSE); - *aLength = 0; - if ((NS_OK == result) && (nsnull != decl)) { + if (decl) { *aLength = decl->Count(); + } else { + *aLength = 0; } return result; @@ -182,7 +184,7 @@ nsDOMCSSDeclaration::Item(PRUint32 aIndex, nsAString& aReturn) nsresult result = GetCSSDeclaration(&decl, PR_FALSE); aReturn.SetLength(0); - if ((NS_OK == result) && (nsnull != decl)) { + if (decl) { result = decl->GetNthProperty(aIndex, aReturn); } @@ -197,8 +199,8 @@ nsDOMCSSDeclaration::GetPropertyValue(const nsAString& aPropertyName, nsCSSDeclaration *decl; nsresult result = GetCSSDeclaration(&decl, PR_FALSE); - aReturn.SetLength(0); - if ((NS_OK == result) && (nsnull != decl)) { + aReturn.Truncate(); + if (decl) { result = decl->GetValue(aPropertyName, aReturn); } @@ -211,18 +213,11 @@ nsDOMCSSDeclaration::GetPropertyPriority(const nsAString& aPropertyName, { nsCSSDeclaration *decl; nsresult result = GetCSSDeclaration(&decl, PR_FALSE); - PRBool isImportant = PR_FALSE; - if ((NS_OK == result) && (nsnull != decl)) { - isImportant = decl->GetValueIsImportant(aPropertyName); - } - - if ((NS_OK == result) && isImportant) { + aReturn.Truncate(); + if (decl && decl->GetValueIsImportant(aPropertyName)) { aReturn.Assign(NS_LITERAL_STRING("important")); } - else { - aReturn.SetLength(0); - } return result; } @@ -252,6 +247,112 @@ nsDOMCSSDeclaration::SetProperty(const nsAString& aPropertyName, PR_TRUE, PR_FALSE); } +NS_IMETHODIMP +nsDOMCSSDeclaration::RemoveProperty(const nsAString& aPropertyName, + nsAString& aReturn) +{ + aReturn.Truncate(); + + nsCSSDeclaration* decl; + nsresult rv = GetCSSDeclaration(&decl, PR_FALSE); + if (!decl) { + return rv; + } + + nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName); + + decl->GetValue(prop, aReturn); + + rv = decl->RemoveProperty(prop); + + if (NS_SUCCEEDED(rv)) { + rv = DeclarationChanged(); + } else { + // RemoveProperty used to throw in all sorts of situations -- e.g. + // if the property was a shorthand one. Do not propagate its return + // value to callers. (XXX or should we propagate it again now?) + rv = NS_OK; + } + + return rv; +} + +nsresult +nsDOMCSSDeclaration::ParsePropertyValue(const nsAString& aPropName, + const nsAString& aPropValue) +{ + nsCSSDeclaration* decl; + nsresult result = GetCSSDeclaration(&decl, PR_TRUE); + if (!decl) { + return result; + } + + nsCOMPtr cssLoader; + nsCOMPtr cssParser; + nsCOMPtr baseURI; + + result = GetCSSParsingEnvironment(getter_AddRefs(baseURI), + getter_AddRefs(cssLoader), + getter_AddRefs(cssParser)); + if (NS_FAILED(result)) { + return result; + } + + nsChangeHint uselessHint = NS_STYLE_HINT_NONE; + result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, + &uselessHint); + if (NS_SUCCEEDED(result)) { + result = DeclarationChanged(); + } + + if (cssLoader) { + cssLoader->RecycleParser(cssParser); + } + + return result; +} + +nsresult +nsDOMCSSDeclaration::ParseDeclaration(const nsAString& aDecl, + PRBool aParseOnlyOneDecl, + PRBool aClearOldDecl) +{ + nsCSSDeclaration* decl; + nsresult result = GetCSSDeclaration(&decl, PR_TRUE); + if (!decl) { + return result; + } + + nsCOMPtr cssLoader; + nsCOMPtr cssParser; + nsCOMPtr baseURI; + + result = GetCSSParsingEnvironment(getter_AddRefs(baseURI), + getter_AddRefs(cssLoader), + getter_AddRefs(cssParser)); + + if (NS_FAILED(result)) { + return result; + } + + nsChangeHint uselessHint = NS_STYLE_HINT_NONE; + result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, + aParseOnlyOneDecl, + &uselessHint, + aClearOldDecl); + + if (NS_SUCCEEDED(result)) { + result = DeclarationChanged(); + } + + if (cssLoader) { + cssLoader->RecycleParser(cssParser); + } + + return result; +} + + ////////////////////////////////////////////////////////////////////////////// CSS2PropertiesTearoff::CSS2PropertiesTearoff(nsISupports *aOuter) diff --git a/mozilla/layout/style/nsDOMCSSDeclaration.h b/mozilla/layout/style/nsDOMCSSDeclaration.h index 7f0e19e2a05..9421f67683e 100644 --- a/mozilla/layout/style/nsDOMCSSDeclaration.h +++ b/mozilla/layout/style/nsDOMCSSDeclaration.h @@ -47,6 +47,7 @@ class nsCSSDeclaration; class nsICSSParser; +class nsICSSLoader; class nsIURI; class nsDOMCSSDeclaration : public nsIDOMCSSStyleDeclaration @@ -56,35 +57,28 @@ public: NS_DECL_ISUPPORTS - // NS_DECL_IDOMCSSSTYLEDECLARATION - NS_IMETHOD GetCssText(nsAString& aCssText); - NS_IMETHOD SetCssText(const nsAString& aCssText); - NS_IMETHOD GetLength(PRUint32* aLength); - NS_IMETHOD GetParentRule(nsIDOMCSSRule** aParentRule); - NS_IMETHOD GetPropertyValue(const nsAString& aPropertyName, - nsAString& aReturn); - NS_IMETHOD GetPropertyCSSValue(const nsAString& aPropertyName, - nsIDOMCSSValue** aReturn); - NS_IMETHOD RemoveProperty(const nsAString& aPropertyName, - nsAString& aReturn) = 0; - NS_IMETHOD GetPropertyPriority(const nsAString& aPropertyName, - nsAString& aReturn); - NS_IMETHOD SetProperty(const nsAString& aPropertyName, - const nsAString& aValue, - const nsAString& aPriority); - NS_IMETHOD Item(PRUint32 aIndex, nsAString& aReturn); - + NS_DECL_NSIDOMCSSSTYLEDECLARATION virtual void DropReference() = 0; - // XXX DeCOMify this, so that |nsCSSDeclaration*| is the return type. +protected: + // Always fills in the out parameter, even on failure, and if the out + // parameter is null the nsresult will be the correct thing to + // propagate. virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate) = 0; - virtual nsresult ParsePropertyValue(const nsAString& aPropName, - const nsAString& aPropValue) = 0; - virtual nsresult ParseDeclaration(const nsAString& aDecl, - PRBool aParseOnlyOneDecl, - PRBool aClearOldDecl) = 0; virtual nsresult GetParent(nsISupports **aParent) = 0; + virtual nsresult DeclarationChanged() = 0; + + // This will only fail if it can't get a parser. This means it can + // return NS_OK without aURI or aCSSLoader being initialized. + virtual nsresult GetCSSParsingEnvironment(nsIURI** aBaseURI, + nsICSSLoader** aCSSLoader, + nsICSSParser** aCSSParser) = 0; + + nsresult ParsePropertyValue(const nsAString& aPropName, + const nsAString& aPropValue); + nsresult ParseDeclaration(const nsAString& aDecl, + PRBool aParseOnlyOneDecl, PRBool aClearOldDecl); protected: virtual ~nsDOMCSSDeclaration(); diff --git a/mozilla/layout/style/nsICSSGroupRule.h b/mozilla/layout/style/nsICSSGroupRule.h index f76a34bb920..210f8287fdc 100644 --- a/mozilla/layout/style/nsICSSGroupRule.h +++ b/mozilla/layout/style/nsICSSGroupRule.h @@ -59,14 +59,13 @@ public: NS_IMETHOD EnumerateRulesForwards(nsISupportsArrayEnumFunc aFunc, void * aData) const = 0; /* - * The next two methods (DeleteStyleRuleAt and InsertStyleRulesAt) - * should never be called unless you have first called WillDirty() - * on the parent stylesheet. After they are called, DidDirty() - * needs to be called on the sheet + * The next three methods should never be called unless you have first + * called WillDirty() on the parent stylesheet. After they are + * called, DidDirty() needs to be called on the sheet. */ NS_IMETHOD DeleteStyleRuleAt(PRUint32 aIndex) = 0; NS_IMETHOD InsertStyleRulesAt(PRUint32 aIndex, nsISupportsArray* aRules) = 0; - + NS_IMETHOD ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) = 0; }; diff --git a/mozilla/layout/style/nsICSSStyleRule.h b/mozilla/layout/style/nsICSSStyleRule.h index c19044afac5..94afae748e4 100644 --- a/mozilla/layout/style/nsICSSStyleRule.h +++ b/mozilla/layout/style/nsICSSStyleRule.h @@ -201,7 +201,18 @@ public: virtual void SetLineNumber(PRUint32 aLineNumber) = 0; virtual nsCSSDeclaration* GetDeclaration(void) const = 0; - virtual void SetDeclaration(nsCSSDeclaration* aDeclaration) = 0; + + /** + * Return a new |nsIStyleRule| instance that replaces the current one, + * due to a change in the |nsCSSDeclaration|. Due to the + * |nsIStyleRule| contract of immutability, this must be called if the + * declaration is modified. + * + * |DeclarationChanged| handles replacing the object in the container + * sheet or group rule if |aHandleContainer| is true. + */ + virtual already_AddRefed + DeclarationChanged(PRBool aHandleContainer) = 0; virtual already_AddRefed GetImportantRule(void) = 0; @@ -211,6 +222,7 @@ public: nsresult NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult, - nsCSSSelectorList* aSelector); + nsCSSSelectorList* aSelector, + nsCSSDeclaration* aDeclaration); #endif /* nsICSSStyleRule_h___ */ diff --git a/mozilla/layout/style/nsICSSStyleSheet.h b/mozilla/layout/style/nsICSSStyleSheet.h index 6ccaa54f77d..7c863be0dba 100644 --- a/mozilla/layout/style/nsICSSStyleSheet.h +++ b/mozilla/layout/style/nsICSSStyleSheet.h @@ -64,12 +64,14 @@ public: NS_IMETHOD PrependStyleRule(nsICSSRule* aRule) = 0; NS_IMETHOD AppendStyleRule(nsICSSRule* aRule) = 0; + NS_IMETHOD ReplaceStyleRule(nsICSSRule* aOld, nsICSSRule* aNew) = 0; NS_IMETHOD StyleRuleCount(PRInt32& aCount) const = 0; NS_IMETHOD GetStyleRuleAt(PRInt32 aIndex, nsICSSRule*& aRule) const = 0; NS_IMETHOD DeleteRuleFromGroup(nsICSSGroupRule* aGroup, PRUint32 aIndex) = 0; NS_IMETHOD InsertRuleIntoGroup(const nsAString & aRule, nsICSSGroupRule* aGroup, PRUint32 aIndex, PRUint32* _retval) = 0; + NS_IMETHOD ReplaceRuleInGroup(nsICSSGroupRule* aGroup, nsICSSRule* aOld, nsICSSRule* aNew) = 0; NS_IMETHOD StyleSheetCount(PRInt32& aCount) const = 0; NS_IMETHOD GetStyleSheetAt(PRInt32 aIndex, nsICSSStyleSheet*& aSheet) const = 0; diff --git a/mozilla/layout/style/nsIStyleRule.h b/mozilla/layout/style/nsIStyleRule.h index d10791c3e38..d67723f1241 100644 --- a/mozilla/layout/style/nsIStyleRule.h +++ b/mozilla/layout/style/nsIStyleRule.h @@ -51,13 +51,54 @@ struct nsRuleData; #define NS_ISTYLE_RULE_IID \ {0x40ae5c90, 0xad6a, 0x11d1, {0x80, 0x31, 0x00, 0x60, 0x08, 0x15, 0x9b, 0x5a}} +/** + * An object implementing |nsIStyleRule| (henceforth, a rule) represents + * immutable stylistic information that either applies or does not apply + * to a given element. It belongs to an object or group of objects that + * implement |nsIStyleSheet| and |nsIStyleRuleProcessor| (henceforth, a + * sheet). + * + * A rule becomes relevant to the computation of style data when + * |nsIStyleRuleProcessor::RulesMatching| creates a rule node that + * points to the rule. (A rule node, |nsRuleNode|, is a node in the + * rule tree, which is a lexicographic tree indexed by rules. The path + * from the root of the rule tree to the |nsRuleNode| for a given + * |nsStyleContext| contains exactly the rules that match the element + * that the style context is for, in priority (weight, origin, + * specificity) order.) + * + * The computation of style data uses the rule tree, which calls + * |nsIStyleRule::MapRuleInfoInto| below. + * + * It is worth emphasizing that the data represented by a rule + * implementation are immutable. When the data need to be changed, a + * new rule object must be created. Failing to do this will lead to + * bugs in the handling of dynamic style changes, since the rule tree + * caches the results of |MapRuleInfoInto|. + * + * |nsIStyleRule| objects are owned by |nsRuleNode| objects (in addition + * to typically being owned by their sheet), which are in turn garbage + * collected (with the garbage collection roots being style contexts). + */ + + class nsIStyleRule : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ISTYLE_RULE_IID) NS_IMETHOD GetStyleSheet(nsIStyleSheet*& aSheet) const = 0; - // The new mapping function. + /** + * |nsIStyleRule::MapRuleInfoInto| is a request to copy all stylistic + * data represented by the rule that: + * + are relevant for |aRuleData->mSID| (the style struct ID) + * + are not already filled into the data struct + * into the appropriate data struct in |aRuleData|. It is important + * that only empty data are filled in, since the rule tree is walked + * from highest priority rule to least, so that the walk can stop if + * all needed data are found. Thus overwriting non-empty data will + * break CSS cascading rules. + */ NS_IMETHOD MapRuleInfoInto(nsRuleData* aRuleData)=0; #ifdef DEBUG diff --git a/mozilla/layout/style/nsRuleNode.cpp b/mozilla/layout/style/nsRuleNode.cpp index 1bb258619e1..f26df07f013 100644 --- a/mozilla/layout/style/nsRuleNode.cpp +++ b/mozilla/layout/style/nsRuleNode.cpp @@ -553,74 +553,31 @@ nsRuleNode::PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched) return NS_OK; } -nsresult -nsRuleNode::ClearCachedData(nsIStyleRule* aRule) -{ - NS_ASSERTION(aRule, "you should be using ClearCachedDataInSubtree"); - - nsRuleNode* ruleDest = this; - while (ruleDest) { - if (ruleDest->mRule == aRule) - break; - ruleDest = ruleDest->mParent; - } - - if (ruleDest) { - NS_ASSERTION(ruleDest->mParent, "node must not be root"); - - // The rule was contained along our branch. We need to blow away - // all cached data along this path. Note that, because of the definition - // of inline style, all nodes along this path must have exactly one child. This - // is not a bushy subtree, and so we know that by clearing this path, we've - // invalidated everything that we need to. - // XXXldb What about !important :hover rules, and such? - nsRuleNode* curr = this; - while (curr) { - curr->mNoneBits &= ~NS_STYLE_INHERIT_MASK; - curr->mDependentBits &= ~NS_STYLE_INHERIT_MASK; - if (curr->mStyleData.mResetData || curr->mStyleData.mInheritedData) - curr->mStyleData.Destroy(0, mPresContext); - - if (curr == ruleDest) - break; - - curr = curr->mParent; - } - } - - return NS_OK; -} - PR_STATIC_CALLBACK(PLDHashOperator) -ClearCachedDataInSubtreeHelper(PLDHashTable *table, PLDHashEntryHdr *hdr, +ClearStyleDataHelper(PLDHashTable *table, PLDHashEntryHdr *hdr, PRUint32 number, void *arg) { ChildrenHashEntry *entry = NS_STATIC_CAST(ChildrenHashEntry*, hdr); - nsIStyleRule* rule = NS_STATIC_CAST(nsIStyleRule*, arg); - entry->mRuleNode->ClearCachedDataInSubtree(rule); + entry->mRuleNode->ClearStyleData(); return PL_DHASH_NEXT; } nsresult -nsRuleNode::ClearCachedDataInSubtree(nsIStyleRule* aRule) +nsRuleNode::ClearStyleData() { - if (aRule == nsnull || mRule == aRule) { - // We have a match. Blow away all data stored at this node. - if (mStyleData.mResetData || mStyleData.mInheritedData) - mStyleData.Destroy(0, mPresContext); + // Blow away all data stored at this node. + if (mStyleData.mResetData || mStyleData.mInheritedData) + mStyleData.Destroy(0, mPresContext); - mNoneBits &= ~NS_STYLE_INHERIT_MASK; - mDependentBits &= ~NS_STYLE_INHERIT_MASK; - - aRule = nsnull; // Cause everything to be blown away in the descendants. - } + mNoneBits &= ~NS_STYLE_INHERIT_MASK; + mDependentBits &= ~NS_STYLE_INHERIT_MASK; if (ChildrenAreHashed()) PL_DHashTableEnumerate(ChildrenHash(), - ClearCachedDataInSubtreeHelper, aRule); + ClearStyleDataHelper, nsnull); else for (nsRuleList* curr = ChildrenList(); curr; curr = curr->mNext) - curr->mRuleNode->ClearCachedDataInSubtree(aRule); + curr->mRuleNode->ClearStyleData(); return NS_OK; } @@ -649,11 +606,7 @@ nsRuleNode::PropagateNoneBit(PRUint32 aBit, nsRuleNode* aHighestNode) inline void nsRuleNode::PropagateDependentBit(PRUint32 aBit, nsRuleNode* aHighestNode) { - if (mDependentBits & aBit) - return; // Already set. - - nsRuleNode* curr = this; - while (curr != aHighestNode) { + for (nsRuleNode* curr = this; curr != aHighestNode; curr = curr->mParent) { if (curr->mDependentBits & aBit) { #ifdef DEBUG while (curr != aHighestNode) { @@ -665,7 +618,6 @@ nsRuleNode::PropagateDependentBit(PRUint32 aBit, nsRuleNode* aHighestNode) } curr->mDependentBits |= aBit; - curr = curr->mParent; } } @@ -1148,223 +1100,223 @@ nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID, } const nsStyleStruct* -nsRuleNode::GetDisplayData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetDisplayData(nsStyleContext* aContext) { nsRuleDataDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Display, mPresContext, aContext); ruleData.mDisplayData = &displayData; - return WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData, aComputeData); + return WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData); } const nsStyleStruct* -nsRuleNode::GetVisibilityData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetVisibilityData(nsStyleContext* aContext) { nsRuleDataDisplay displayData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Visibility, mPresContext, aContext); ruleData.mDisplayData = &displayData; - return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData, aComputeData); + return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData); } const nsStyleStruct* -nsRuleNode::GetTextData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetTextData(nsStyleContext* aContext) { nsRuleDataText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Text, mPresContext, aContext); ruleData.mTextData = &textData; - return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData, aComputeData); + return WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData); } const nsStyleStruct* -nsRuleNode::GetTextResetData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetTextResetData(nsStyleContext* aContext) { nsRuleDataText textData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TextReset, mPresContext, aContext); ruleData.mTextData = &textData; - return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData, aComputeData); + return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData); } const nsStyleStruct* -nsRuleNode::GetUserInterfaceData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetUserInterfaceData(nsStyleContext* aContext) { nsRuleDataUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UserInterface, mPresContext, aContext); ruleData.mUserInterfaceData = &uiData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData, aComputeData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData); uiData.mCursor = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetUIResetData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetUIResetData(nsStyleContext* aContext) { nsRuleDataUserInterface uiData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_UIReset, mPresContext, aContext); ruleData.mUserInterfaceData = &uiData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData, aComputeData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData); uiData.mKeyEquivalent = nsnull; return res; } const nsStyleStruct* -nsRuleNode::GetFontData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetFontData(nsStyleContext* aContext) { nsRuleDataFont fontData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Font, mPresContext, aContext); ruleData.mFontData = &fontData; - return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData, aComputeData); + return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData); } const nsStyleStruct* -nsRuleNode::GetColorData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetColorData(nsStyleContext* aContext) { nsRuleDataColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Color, mPresContext, aContext); ruleData.mColorData = &colorData; - return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData, aComputeData); + return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData); } const nsStyleStruct* -nsRuleNode::GetBackgroundData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetBackgroundData(nsStyleContext* aContext) { nsRuleDataColor colorData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Background, mPresContext, aContext); ruleData.mColorData = &colorData; - return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData, aComputeData); + return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData); } const nsStyleStruct* -nsRuleNode::GetMarginData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetMarginData(nsStyleContext* aContext) { nsRuleDataMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Margin, mPresContext, aContext); ruleData.mMarginData = &marginData; - return WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData, aComputeData); + return WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData); } const nsStyleStruct* -nsRuleNode::GetBorderData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetBorderData(nsStyleContext* aContext) { nsRuleDataMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Border, mPresContext, aContext); ruleData.mMarginData = &marginData; - return WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData, aComputeData); + return WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData); } const nsStyleStruct* -nsRuleNode::GetPaddingData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetPaddingData(nsStyleContext* aContext) { nsRuleDataMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Padding, mPresContext, aContext); ruleData.mMarginData = &marginData; - return WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData, aComputeData); + return WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData); } const nsStyleStruct* -nsRuleNode::GetOutlineData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetOutlineData(nsStyleContext* aContext) { nsRuleDataMargin marginData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Outline, mPresContext, aContext); ruleData.mMarginData = &marginData; - return WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData, aComputeData); + return WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData); } const nsStyleStruct* -nsRuleNode::GetListData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetListData(nsStyleContext* aContext) { nsRuleDataList listData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_List, mPresContext, aContext); ruleData.mListData = &listData; - return WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData, aComputeData); + return WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData); } const nsStyleStruct* -nsRuleNode::GetPositionData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetPositionData(nsStyleContext* aContext) { nsRuleDataPosition posData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Position, mPresContext, aContext); ruleData.mPositionData = &posData; - return WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData, aComputeData); + return WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData); } const nsStyleStruct* -nsRuleNode::GetTableData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetTableData(nsStyleContext* aContext) { nsRuleDataTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Table, mPresContext, aContext); ruleData.mTableData = &tableData; - return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData, aComputeData); + return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData); } const nsStyleStruct* -nsRuleNode::GetTableBorderData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetTableBorderData(nsStyleContext* aContext) { nsRuleDataTable tableData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_TableBorder, mPresContext, aContext); ruleData.mTableData = &tableData; - return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData, aComputeData); + return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData); } const nsStyleStruct* -nsRuleNode::GetContentData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetContentData(nsStyleContext* aContext) { nsRuleDataContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Content, mPresContext, aContext); ruleData.mContentData = &contentData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData, aComputeData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData); contentData.mCounterIncrement = contentData.mCounterReset = nsnull; contentData.mContent = nsnull; // We are sharing with some style rule. It really owns the data. return res; } const nsStyleStruct* -nsRuleNode::GetQuotesData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetQuotesData(nsStyleContext* aContext) { nsRuleDataContent contentData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_Quotes, mPresContext, aContext); ruleData.mContentData = &contentData; - const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData, aComputeData); + const nsStyleStruct* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData); contentData.mQuotes = nsnull; // We are sharing with some style rule. It really owns the data. return res; } const nsStyleStruct* -nsRuleNode::GetXULData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetXULData(nsStyleContext* aContext) { nsRuleDataXUL xulData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_XUL, mPresContext, aContext); ruleData.mXULData = &xulData; - return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData, aComputeData); + return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData); } #ifdef MOZ_SVG const nsStyleStruct* -nsRuleNode::GetSVGData(nsStyleContext* aContext, PRBool aComputeData) +nsRuleNode::GetSVGData(nsStyleContext* aContext) { nsRuleDataSVG svgData; // Declare a struct with null CSS values. nsRuleData ruleData(eStyleStruct_SVG, mPresContext, aContext); ruleData.mSVGData = &svgData; - return WalkRuleTree(eStyleStruct_SVG, aContext, &ruleData, &svgData, aComputeData); + return WalkRuleTree(eStyleStruct_SVG, aContext, &ruleData, &svgData); } #endif @@ -1372,8 +1324,7 @@ const nsStyleStruct* nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, nsStyleContext* aContext, nsRuleData* aRuleData, - nsRuleDataStruct* aSpecificData, - PRBool aComputeData) + nsRuleDataStruct* aSpecificData) { // We start at the most specific rule in the tree. nsStyleStruct* startStruct = nsnull; @@ -1496,9 +1447,6 @@ nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, } // We need to compute the data from the information that the rules specified. - if (!aComputeData) - return nsnull; - ComputeStyleDataFn fn = gComputeStyleDataFn[aSID]; const nsStyleStruct* res = (this->*fn)(startStruct, *aSpecificData, aContext, highestNode, detail, !aRuleData->mCanStoreInRuleTree); @@ -4491,14 +4439,17 @@ nsRuleNode::GetStyleData(nsStyleStructID aSID, NS_NOTREACHED("dependent bits set but no cached struct present"); } + if (!aComputeData) + return nsnull; + // Nothing is cached. We'll have to delve further and examine our rules. GetStyleDataFn fn = gGetStyleDataFn[aSID]; if (!fn) { NS_NOTREACHED("unknown style struct requested"); return nsnull; } - data = (this->*fn)(aContext, aComputeData); - if (data || !aComputeData) + data = (this->*fn)(aContext); + if (data) return data; NS_NOTREACHED("could not create style struct"); diff --git a/mozilla/layout/style/nsRuleNode.h b/mozilla/layout/style/nsRuleNode.h index b5df7848fdd..c2532afc8cb 100644 --- a/mozilla/layout/style/nsRuleNode.h +++ b/mozilla/layout/style/nsRuleNode.h @@ -410,8 +410,7 @@ protected: const nsStyleStruct* WalkRuleTree(const nsStyleStructID aSID, nsStyleContext* aContext, nsRuleData* aRuleData, - nsRuleDataStruct* aSpecificData, - PRBool aComputeData); + nsRuleDataStruct* aSpecificData); const nsStyleStruct* ComputeDisplayData(nsStyleStruct* aStartDisplay, const nsRuleDataStruct& aDisplayData, nsStyleContext* aContext, nsRuleNode* aHighestNode, @@ -504,31 +503,31 @@ protected: inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID, const nsRuleDataStruct& aRuleDataStruct); const nsStyleStruct* GetParentData(const nsStyleStructID aSID); - const nsStyleStruct* GetDisplayData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetVisibilityData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetFontData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetColorData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetBackgroundData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetMarginData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetBorderData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetPaddingData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetOutlineData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetListData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetPositionData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetTableData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetTableBorderData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetContentData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetQuotesData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetTextData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetTextResetData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetUserInterfaceData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetUIResetData(nsStyleContext* aContext, PRBool aComputeData); - const nsStyleStruct* GetXULData(nsStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetDisplayData(nsStyleContext* aContext); + const nsStyleStruct* GetVisibilityData(nsStyleContext* aContext); + const nsStyleStruct* GetFontData(nsStyleContext* aContext); + const nsStyleStruct* GetColorData(nsStyleContext* aContext); + const nsStyleStruct* GetBackgroundData(nsStyleContext* aContext); + const nsStyleStruct* GetMarginData(nsStyleContext* aContext); + const nsStyleStruct* GetBorderData(nsStyleContext* aContext); + const nsStyleStruct* GetPaddingData(nsStyleContext* aContext); + const nsStyleStruct* GetOutlineData(nsStyleContext* aContext); + const nsStyleStruct* GetListData(nsStyleContext* aContext); + const nsStyleStruct* GetPositionData(nsStyleContext* aContext); + const nsStyleStruct* GetTableData(nsStyleContext* aContext); + const nsStyleStruct* GetTableBorderData(nsStyleContext* aContext); + const nsStyleStruct* GetContentData(nsStyleContext* aContext); + const nsStyleStruct* GetQuotesData(nsStyleContext* aContext); + const nsStyleStruct* GetTextData(nsStyleContext* aContext); + const nsStyleStruct* GetTextResetData(nsStyleContext* aContext); + const nsStyleStruct* GetUserInterfaceData(nsStyleContext* aContext); + const nsStyleStruct* GetUIResetData(nsStyleContext* aContext); + const nsStyleStruct* GetXULData(nsStyleContext* aContext); #ifdef MOZ_SVG - const nsStyleStruct* GetSVGData(nsStyleContext* aContext, PRBool aComputeData); + const nsStyleStruct* GetSVGData(nsStyleContext* aContext); #endif - typedef const nsStyleStruct* (nsRuleNode::*GetStyleDataFn)(nsStyleContext*, PRBool); + typedef const nsStyleStruct* (nsRuleNode::*GetStyleDataFn)(nsStyleContext*); static GetStyleDataFn gGetStyleDataFn[]; public: @@ -557,8 +556,7 @@ public: return mPresContext; } - nsresult ClearCachedData(nsIStyleRule* aRule); - nsresult ClearCachedDataInSubtree(nsIStyleRule* aRule); + nsresult ClearStyleData(); nsresult GetPresContext(nsIPresContext** aResult); nsresult PathContainsRule(nsIStyleRule* aRule, PRBool* aMatched); const nsStyleStruct* GetStyleData(nsStyleStructID aSID, diff --git a/mozilla/layout/style/nsStyleContext.cpp b/mozilla/layout/style/nsStyleContext.cpp index 810984b4290..f6daeb03e54 100644 --- a/mozilla/layout/style/nsStyleContext.cpp +++ b/mozilla/layout/style/nsStyleContext.cpp @@ -396,27 +396,20 @@ nsStyleContext::ApplyStyleFixups(nsIPresContext* aPresContext) } void -nsStyleContext::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule) +nsStyleContext::ClearStyleData(nsIPresContext* aPresContext) { - PRBool matched = PR_TRUE; - if (aRule) - mRuleNode->PathContainsRule(aRule, &matched); - - if (matched) { - // First we need to clear out all of our style data. - if (mCachedStyleData.mResetData || mCachedStyleData.mInheritedData) - mCachedStyleData.Destroy(mBits, aPresContext); + // First we need to clear out all of our style data. + if (mCachedStyleData.mResetData || mCachedStyleData.mInheritedData) + mCachedStyleData.Destroy(mBits, aPresContext); - mBits = 0; // Clear all bits. - aRule = nsnull; // Force all structs to be blown away in the children. - } + mBits = 0; // Clear all bits. ApplyStyleFixups(aPresContext); if (mChild) { nsStyleContext* child = mChild; do { - child->ClearStyleData(aPresContext, aRule); + child->ClearStyleData(aPresContext); child = child->mNextSibling; } while (mChild != child); } @@ -424,7 +417,7 @@ nsStyleContext::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule if (mEmptyChild) { nsStyleContext* child = mEmptyChild; do { - child->ClearStyleData(aPresContext, aRule); + child->ClearStyleData(aPresContext); child = child->mNextSibling; } while (mEmptyChild != child); } diff --git a/mozilla/layout/style/nsStyleContext.h b/mozilla/layout/style/nsStyleContext.h index 1f480293632..be3629234e8 100644 --- a/mozilla/layout/style/nsStyleContext.h +++ b/mozilla/layout/style/nsStyleContext.h @@ -139,7 +139,7 @@ public: nsStyleStruct* GetUniqueStyleData(nsIPresContext* aPresContext, const nsStyleStructID& aSID); - void ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule); + void ClearStyleData(nsIPresContext* aPresContext); nsChangeHint CalcStyleDifference(nsStyleContext* aOther); diff --git a/mozilla/layout/style/nsStyleSet.cpp b/mozilla/layout/style/nsStyleSet.cpp index be03afc5468..9baf2b190e9 100644 --- a/mozilla/layout/style/nsStyleSet.cpp +++ b/mozilla/layout/style/nsStyleSet.cpp @@ -195,7 +195,7 @@ public: virtual nsresult GetRuleTree(nsRuleNode** aResult); - virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule); + virtual nsresult ClearStyleData(nsIPresContext* aPresContext); virtual nsresult GetStyleFrameConstruction(nsIStyleFrameConstruction** aResult) { *aResult = mFrameConstructor; @@ -254,20 +254,6 @@ public: PRInt32 aModType, nsChangeHint aHint); // See nsStyleConsts fot hint values - // xxx style rules enumeration - - // Style change notifications - NS_IMETHOD StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint); // See nsStyleConsts fot hint values - NS_IMETHOD StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - NS_IMETHOD StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule); - // Notification that we were unable to render a replaced element. NS_IMETHOD CantRenderReplacedElement(nsIPresContext* aPresContext, nsIFrame* aFrame); @@ -1504,30 +1490,13 @@ StyleSetImpl::GetDefaultStyleData() } nsresult -StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule) +StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext) { - // XXXdwh This is not terribly fast, but fortunately this case is rare (and often a full tree - // invalidation anyway). Improving performance here would involve a footprint - // increase. Mappings from rule nodes to their associated style contexts as well as - // mappings from rules to their associated rule nodes would enable us to avoid the two - // tree walks that occur here. - - // Crawl the entire rule tree and blow away all data for rule nodes (and their descendants) - // that have the given rule. if (mRuleTree) - mRuleTree->ClearCachedDataInSubtree(aRule); - - // We need to crawl the entire style context tree, and for each style context we need - // to see if the specified rule is matched. If so, that context and all its descendant - // contexts must have their data wiped. - nsCOMPtr shell; - aPresContext->GetShell(getter_AddRefs(shell)); - nsIFrame* rootFrame; - shell->GetRootFrame(&rootFrame); - if (rootFrame) { - nsStyleContext* rootContext = rootFrame->GetStyleContext(); - if (rootContext) - rootContext->ClearStyleData(aPresContext, aRule); + mRuleTree->ClearStyleData(); + + for (PRInt32 i = mRoots.Count() - 1; i >= 0; --i) { + NS_STATIC_CAST(nsStyleContext*,mRoots[i])->ClearStyleData(aPresContext); } return NS_OK; @@ -1761,33 +1730,6 @@ StyleSetImpl::AttributeChanged(nsIPresContext* aPresContext, aNameSpaceID, aAttribute, aModType, aHint); } - -// Style change notifications -NS_IMETHODIMP -StyleSetImpl::StyleRuleChanged(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule, - nsChangeHint aHint) -{ - return mFrameConstructor->StyleRuleChanged(aPresContext, aStyleSheet, aStyleRule, aHint); -} - -NS_IMETHODIMP -StyleSetImpl::StyleRuleAdded(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) -{ - return mFrameConstructor->StyleRuleAdded(aPresContext, aStyleSheet, aStyleRule); -} - -NS_IMETHODIMP -StyleSetImpl::StyleRuleRemoved(nsIPresContext* aPresContext, - nsIStyleSheet* aStyleSheet, - nsIStyleRule* aStyleRule) -{ - return mFrameConstructor->StyleRuleRemoved(aPresContext, aStyleSheet, aStyleRule); -} - NS_IMETHODIMP StyleSetImpl::CantRenderReplacedElement(nsIPresContext* aPresContext, nsIFrame* aFrame)