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)