From 3b86a016bbeda003097f341b7faa5c9d9fe39b24 Mon Sep 17 00:00:00 2001 From: "dbaron%dbaron.org" Date: Thu, 6 Mar 2003 19:07:22 +0000 Subject: [PATCH] Handle inline style changes by creating new style rules to wrap the modified nsCSSDeclarations, thus moving towards style rule immutability and away from property-based change hints. Patch from Boris Zbarsky . r=dbaron sr=roc b=171830 git-svn-id: svn://10.0.0.236/trunk@139034 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/content/base/src/nsRuleNode.cpp | 18 +- mozilla/content/base/src/nsStyleSet.cpp | 103 ++------- .../html/content/src/nsGenericHTMLElement.cpp | 27 --- .../content/html/style/src/nsCSSStyleRule.cpp | 16 +- .../style/src/nsDOMCSSAttrDeclaration.cpp | 215 ++++++------------ .../html/style/src/nsDOMCSSAttrDeclaration.h | 3 +- .../html/style/src/nsDOMCSSDeclaration.h | 3 - .../html/style/src/nsHTMLCSSStyleSheet.cpp | 2 +- mozilla/content/shared/public/nsRuleNode.h | 2 +- mozilla/content/shared/public/nsRuleWalker.h | 4 +- mozilla/layout/base/nsCSSFrameConstructor.cpp | 77 +------ mozilla/layout/base/nsCSSFrameConstructor.h | 5 +- mozilla/layout/base/nsPresContext.cpp | 2 +- mozilla/layout/base/nsPresShell.cpp | 2 +- mozilla/layout/base/public/nsIStyleSet.h | 10 +- mozilla/layout/base/src/nsPresContext.cpp | 2 +- mozilla/layout/html/base/src/nsPresShell.cpp | 2 +- .../html/style/src/nsCSSFrameConstructor.cpp | 77 +------ .../html/style/src/nsCSSFrameConstructor.h | 5 +- mozilla/layout/style/nsCSSStyleRule.cpp | 16 +- .../layout/style/nsDOMCSSAttrDeclaration.cpp | 215 ++++++------------ .../layout/style/nsDOMCSSAttrDeclaration.h | 3 +- mozilla/layout/style/nsDOMCSSDeclaration.h | 3 - mozilla/layout/style/nsHTMLCSSStyleSheet.cpp | 2 +- mozilla/layout/style/nsRuleNode.cpp | 18 +- mozilla/layout/style/nsRuleNode.h | 2 +- mozilla/layout/style/nsRuleWalker.h | 4 +- mozilla/layout/style/nsStyleSet.cpp | 103 ++------- 28 files changed, 235 insertions(+), 706 deletions(-) diff --git a/mozilla/content/base/src/nsRuleNode.cpp b/mozilla/content/base/src/nsRuleNode.cpp index 270f7bc6cef..689efb56739 100644 --- a/mozilla/content/base/src/nsRuleNode.cpp +++ b/mozilla/content/base/src/nsRuleNode.cpp @@ -470,7 +470,7 @@ nsRuleNode::GetBits(PRInt32 aType, PRUint32* aResult) } nsresult -nsRuleNode::Transition(nsIStyleRule* aRule, PRBool aIsInlineStyle, nsRuleNode** aResult) +nsRuleNode::Transition(nsIStyleRule* aRule, nsRuleNode** aResult) { nsRuleNode* next = nsnull; @@ -513,21 +513,7 @@ nsRuleNode::Transition(nsIStyleRule* aRule, PRBool aIsInlineStyle, nsRuleNode** SetChildrenList(new (mPresContext) nsRuleList(next, ChildrenList())); createdNode = PR_TRUE; } - - if (aIsInlineStyle && createdNode) { - // We just made a new rule node for an inline style rule (e.g., for - // the style attribute on an HTML, SVG, or XUL element). In order to - // fix bug 99344, we have to maintain a mapping from inline style rules - // to all the rule nodes in a rule tree that correspond to the inline - // style rule. - // Obtain our style set and then add this rule node to our mapping. - nsCOMPtr shell; - mPresContext->GetShell(getter_AddRefs(shell)); - nsCOMPtr styleSet; - shell->GetStyleSet(getter_AddRefs(styleSet)); - styleSet->AddRuleNodeMapping(next); - } - + *aResult = next; return NS_OK; } diff --git a/mozilla/content/base/src/nsStyleSet.cpp b/mozilla/content/base/src/nsStyleSet.cpp index c70b97619f8..5f4aaa7b1e1 100644 --- a/mozilla/content/base/src/nsStyleSet.cpp +++ b/mozilla/content/base/src/nsStyleSet.cpp @@ -189,9 +189,7 @@ public: virtual nsresult GetRuleTree(nsRuleNode** aResult); virtual nsresult ClearCachedDataInRuleTree(nsIStyleRule* aRule); - virtual nsresult AddRuleNodeMapping(nsRuleNode* aRuleNode); - - virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsStyleContext* aContext); + virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule); virtual nsresult GetStyleFrameConstruction(nsIStyleFrameConstruction** aResult) { *aResult = mFrameConstructor; @@ -369,7 +367,6 @@ protected: nsRuleNode* mOldRuleTree; // Used during rule tree reconstruction. nsRuleWalker* mRuleWalker; // This is an instance of a rule walker that can be used // to navigate through our tree. - nsHashtable mRuleMappings; // A hashtable from rules to rule node lists. MOZ_TIMER_DECLARE(mStyleResolutionWatch) @@ -387,8 +384,7 @@ StyleSetImpl::StyleSetImpl() mQuirkStyleSheet(nsnull), mRuleTree(nsnull), mOldRuleTree(nsnull), - mRuleWalker(nsnull), - mRuleMappings(32) + mRuleWalker(nsnull) #ifdef MOZ_PERF_METRICS ,mTimerEnabled(PR_FALSE) #endif @@ -1361,9 +1357,6 @@ PRBool PR_CALLBACK DeleteRuleNodeLists(nsHashKey* aKey, void* aData, void* aClos NS_IMETHODIMP StyleSetImpl::Shutdown() { - mRuleMappings.Enumerate(DeleteRuleNodeLists); - mRuleMappings.Reset(); - delete mRuleWalker; if (mRuleTree) { @@ -1380,17 +1373,6 @@ StyleSetImpl::GetRuleTree(nsRuleNode** aResult) return NS_OK; } -nsresult -StyleSetImpl::AddRuleNodeMapping(nsRuleNode* aRuleNode) -{ - nsVoidKey key(aRuleNode->Rule()); - nsRuleNodeList* ruleList = - new (aRuleNode->PresContext()) nsRuleNodeList(aRuleNode, - NS_STATIC_CAST(nsRuleNodeList*, mRuleMappings.Get(&key))); - mRuleMappings.Put(&key, ruleList); - return NS_OK; -} - nsresult StyleSetImpl::BeginRuleTreeReconstruct() { @@ -1398,8 +1380,6 @@ StyleSetImpl::BeginRuleTreeReconstruct() mRuleWalker = nsnull; mOldRuleTree = mRuleTree; mRuleTree = nsnull; - mRuleMappings.Enumerate(DeleteRuleNodeLists); - mRuleMappings.Reset(); return NS_OK; } @@ -1422,63 +1402,30 @@ StyleSetImpl::ClearCachedDataInRuleTree(nsIStyleRule* aInlineStyleRule) } nsresult -StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsStyleContext* aContext) +StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule) { - // XXXdwh. If we're willing to *really* optimize this - // invalidation, we could only invalidate the struct data - // that actually changed. For example, if someone changes - // style.left, we really only need to blow away cached - // data in the position struct. - if (aContext) { - // |aRule| should never be null, but we'll sanity check it just in case. - if (aRule) { - // Obtain our rule node list and clear out the cached data in all rule nodes - // that correspond to this rule. See bug 99344 for more details as to how - // inline style rules can end up with multiple rule nodes in a rule tree. - nsVoidKey key(aRule); - nsRuleNodeList* ruleList = NS_STATIC_CAST(nsRuleNodeList*, mRuleMappings.Get(&key)); - for ( ; ruleList; ruleList = ruleList->mNext) - ruleList->mRuleNode->ClearCachedData(aRule); - } - - // XXXdwh I'm just being paranoid here. Also clear out the data starting at the style - // context's rule node. This really should always be done in the for loop above, - // but I'm going to leave this here just in case (for now). - nsRuleNode* ruleNode; - aContext->GetRuleNode(&ruleNode); - ruleNode->ClearCachedData(aRule); - - // XXX We need to clear style data here in case there's a style context - // that inherits a struct from its parent where the parent uses data - // that's cached on the rule node. Otherwise we could crash while - // doing checks comparing old data to new data during reresolution. - // This could make some of those checks incorrect. - aContext->ClearStyleData(aPresContext, nsnull); - } - else { - // 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); - } + // 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); } return NS_OK; diff --git a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp index a78a76f0a02..5f92daa9c60 100644 --- a/mozilla/content/html/content/src/nsGenericHTMLElement.cpp +++ b/mozilla/content/html/content/src/nsGenericHTMLElement.cpp @@ -1953,21 +1953,6 @@ nsGenericHTMLElement::SetHTMLAttribute(nsIAtom* aAttribute, mDocument->BeginUpdate(); mDocument->AttributeWillChange(this, kNameSpaceID_None, aAttribute); - - if (nsHTMLAtoms::style == aAttribute) { - nsHTMLValue oldValue; - nsChangeHint oldImpact = NS_STYLE_HINT_NONE; - // Either we have no listeners or it's a real modification. To - // cover the former case we need to check the return value of - // GetHTMLAttribute - if (modification && - NS_CONTENT_ATTR_NOT_THERE != GetHTMLAttribute(aAttribute, - oldValue)) { - oldImpact = GetStyleImpactFrom(oldValue); - } - impact = GetStyleImpactFrom(aValue); - NS_UpdateHint(impact, oldImpact); - } } sheet = dont_AddRef(GetAttrStyleSheet(mDocument)); if (sheet) { @@ -3194,18 +3179,6 @@ nsGenericHTMLElement::GetCommonMappedAttributesImpact(const nsIAtom* aAttribute, aHint = NS_STYLE_HINT_REFLOW; // LANG attribute affects font selection return PR_TRUE; } - /* - We should not REFRAME for a class change; - let the resulting style decide the impact - (bug 21225, mja) - */ -#if 0 - else if (nsHTMLAtoms::kClass == aAttribute) { // bug 8862 - aHint = NS_STYLE_HINT_FRAMECHANGE; - return PR_TRUE; - } -#endif - else if (nsHTMLAtoms::_baseHref == aAttribute) { aHint = NS_STYLE_HINT_VISUAL; // at a minimum, elements may need to override return PR_TRUE; diff --git a/mozilla/content/html/style/src/nsCSSStyleRule.cpp b/mozilla/content/html/style/src/nsCSSStyleRule.cpp index b4a944a6835..0246fc077ad 100644 --- a/mozilla/content/html/style/src/nsCSSStyleRule.cpp +++ b/mozilla/content/html/style/src/nsCSSStyleRule.cpp @@ -901,7 +901,6 @@ public: virtual void DropReference(void); virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate); - virtual nsresult SetCSSDeclaration(nsCSSDeclaration *aDecl); virtual nsresult GetCSSParsingEnvironment(nsICSSStyleRule* aRule, nsICSSStyleSheet** aSheet, nsIDocument** aDocument, @@ -1006,16 +1005,6 @@ DOMCSSDeclarationImpl::GetCSSDeclaration(nsCSSDeclaration **aDecl, return NS_OK; } -nsresult -DOMCSSDeclarationImpl::SetCSSDeclaration(nsCSSDeclaration *aDecl) -{ - if (mRule) { - mRule->SetDeclaration(aDecl); - } - - return NS_OK; -} - /* * 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, @@ -1152,10 +1141,7 @@ DOMCSSDeclarationImpl::ParseDeclaration(const nsAString& aDecl, result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, aParseOnlyOneDecl, &hint); - if (result == NS_CSS_PARSER_DROP_DECLARATION) { - SetCSSDeclaration(declClone); - result = NS_OK; - } else if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(result)) { if (cssSheet) { cssSheet->SetModified(PR_TRUE); } diff --git a/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.cpp b/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.cpp index 0a583fda8ac..df88034c175 100644 --- a/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.cpp +++ b/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.cpp @@ -73,42 +73,16 @@ nsDOMCSSAttributeDeclaration::RemoveProperty(const nsAString& aPropertyName, nsAString& aReturn) { nsCSSDeclaration* decl; - nsresult rv = GetCSSDeclaration(&decl, PR_TRUE); - - if (NS_SUCCEEDED(rv) && decl && mContent) { - nsCOMPtr doc; - mContent->GetDocument(*getter_AddRefs(doc)); - - if (doc) { - doc->BeginUpdate(); - - doc->AttributeWillChange(mContent, kNameSpaceID_None, - nsHTMLAtoms::style); - } - - nsChangeHint hint = NS_STYLE_HINT_NONE; + nsresult rv = GetCSSDeclaration(&decl, PR_FALSE); + if (NS_SUCCEEDED(rv) && decl) { nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName); nsCSSValue val; rv = decl->RemoveProperty(prop, val); if (NS_SUCCEEDED(rv)) { - // We pass in eCSSProperty_UNKNOWN here so that we don't get the - // property name in the return string. - val.ToString(aReturn, eCSSProperty_UNKNOWN); - hint = 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 (doc) { - doc->AttributeChanged(mContent, kNameSpaceID_None, nsHTMLAtoms::style, - nsIDOMMutationEvent::MODIFICATION, - hint); - doc->EndUpdate(); + rv = SetCSSDeclaration(decl, PR_TRUE); } } @@ -121,6 +95,23 @@ nsDOMCSSAttributeDeclaration::DropReference() mContent = nsnull; } +nsresult +nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration* aDecl, + PRBool aNotify) +{ + NS_ASSERTION(mContent, "Must have content node to set the decl!"); + + nsCOMPtr cssRule; + nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsCSSSelector()); + NS_ENSURE_SUCCESS(rv, rv); + + cssRule->SetDeclaration(aDecl); + cssRule->SetWeight(PR_INT32_MAX); + return mContent->SetHTMLAttribute(nsHTMLAtoms::style, + nsHTMLValue(cssRule), + aNotify); +} + nsresult nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate) @@ -130,8 +121,9 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, *aDecl = nsnull; if (mContent) { nsHTMLValue val; - mContent->GetHTMLAttribute(nsHTMLAtoms::style, val); - if (eHTMLUnit_ISupports == val.GetUnit()) { + result = mContent->GetHTMLAttribute(nsHTMLAtoms::style, val); + if (result == NS_CONTENT_ATTR_HAS_VALUE && + eHTMLUnit_ISupports == val.GetUnit()) { nsCOMPtr rule = val.GetISupportsValue(); nsCOMPtr cssRule = do_QueryInterface(rule, &result); if (cssRule) { @@ -140,17 +132,9 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, } else if (aAllocate) { result = NS_NewCSSDeclaration(aDecl); - if (NS_OK == result) { - nsCOMPtr cssRule; - result = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsCSSSelector()); - if (NS_OK == result) { - cssRule->SetDeclaration(*aDecl); - cssRule->SetWeight(0x7fffffff); - result = mContent->SetHTMLAttribute(nsHTMLAtoms::style, - nsHTMLValue(cssRule), - PR_FALSE); - } - else { + if (NS_SUCCEEDED(result)) { + result = SetCSSDeclaration(*aDecl, PR_FALSE); + if (NS_FAILED(result)) { (*aDecl)->RuleAbort(); *aDecl = nsnull; } @@ -161,26 +145,6 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, return result; } -nsresult -nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration *aDecl) -{ - nsresult result = NS_OK; - - if (mContent) { - nsHTMLValue val; - mContent->GetHTMLAttribute(nsHTMLAtoms::style, val); - if (eHTMLUnit_ISupports == val.GetUnit()) { - nsCOMPtr rule = val.GetISupportsValue(); - nsCOMPtr cssRule = do_QueryInterface(rule, &result); - if (cssRule) { - cssRule->SetDeclaration(aDecl); - } - } - } - - return result; -} - /* * 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 @@ -247,12 +211,6 @@ nsDOMCSSAttributeDeclaration::ParsePropertyValue(const nsAString& aPropName, nsCOMPtr cssLoader; nsCOMPtr cssParser; nsCOMPtr baseURI; - nsCOMPtr doc; - - result = mContent->GetDocument(*getter_AddRefs(doc)); - if (NS_FAILED(result)) { - return result; - } result = GetCSSParsingEnvironment(mContent, getter_AddRefs(baseURI), @@ -262,24 +220,18 @@ nsDOMCSSAttributeDeclaration::ParsePropertyValue(const nsAString& aPropName, return result; } - nsChangeHint hint = NS_STYLE_HINT_NONE; - if (doc) { - doc->BeginUpdate(); - doc->AttributeWillChange(mContent, kNameSpaceID_None, nsHTMLAtoms::style); - } - - result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, &hint); - if (doc) { - doc->AttributeChanged(mContent, kNameSpaceID_None, nsHTMLAtoms::style, - nsIDOMMutationEvent::MODIFICATION, hint); - doc->EndUpdate(); + nsChangeHint uselessHint = NS_STYLE_HINT_NONE; + result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, + &uselessHint); + if (NS_SUCCEEDED(result)) { + result = SetCSSDeclaration(decl, PR_TRUE); } if (cssLoader) { cssLoader->RecycleParser(cssParser); } - return NS_OK; + return result; } nsresult @@ -290,70 +242,51 @@ nsDOMCSSAttributeDeclaration::ParseDeclaration(const nsAString& aDecl, nsCSSDeclaration* decl; nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - if (decl) { - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - nsCOMPtr doc; + if (!decl) { + return result; + } - result = mContent->GetDocument(*getter_AddRefs(doc)); - if (NS_FAILED(result)) { - 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; + } + + if (aClearOldDecl) { + // This should be done with decl->Clear() once such a method exists. + nsAutoString propName; + PRUint32 count, i; + + count = decl->Count(); + + for (i = 0; i < count; i++) { + decl->GetNthProperty(0, propName); + + nsCSSProperty prop = nsCSSProps::LookupProperty(propName); + nsCSSValue val; + + decl->RemoveProperty(prop, val); } - result = GetCSSParsingEnvironment(mContent, - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - - if (NS_SUCCEEDED(result)) { - nsChangeHint hint = NS_STYLE_HINT_NONE; - if (doc) { - doc->BeginUpdate(); - - doc->AttributeWillChange(mContent, kNameSpaceID_None, - nsHTMLAtoms::style); - } - nsCSSDeclaration* declClone = decl->Clone(); - - if (aClearOldDecl) { - hint = decl->GetStyleImpact(); - // This should be done with decl->Clear() once such a method exists. - nsAutoString propName; - PRUint32 count, i; - - count = decl->Count(); - - for (i = 0; i < count; i++) { - decl->GetNthProperty(0, propName); - - nsCSSProperty prop = nsCSSProps::LookupProperty(propName); - nsCSSValue val; - - decl->RemoveProperty(prop, val); - } - } + } - nsChangeHint newHint = NS_STYLE_HINT_NONE; - result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, - aParseOnlyOneDecl, &newHint); - NS_UpdateHint(hint, newHint); - - if (result == NS_CSS_PARSER_DROP_DECLARATION) { - SetCSSDeclaration(declClone); - result = NS_OK; - } - if (doc) { - if (NS_SUCCEEDED(result) && result != NS_CSS_PARSER_DROP_DECLARATION) { - doc->AttributeChanged(mContent, kNameSpaceID_None, - nsHTMLAtoms::style, - nsIDOMMutationEvent::MODIFICATION, hint); - } - doc->EndUpdate(); - } - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - } + nsChangeHint uselessHint = NS_STYLE_HINT_NONE; + result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, + aParseOnlyOneDecl, + &uselessHint); + + if (NS_SUCCEEDED(result)) { + result = SetCSSDeclaration(decl, PR_TRUE); + } + + if (cssLoader) { + cssLoader->RecycleParser(cssParser); } return result; diff --git a/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.h b/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.h index 14ae2e5b3b8..d080f2c0be8 100644 --- a/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.h +++ b/mozilla/content/html/style/src/nsDOMCSSAttrDeclaration.h @@ -61,7 +61,6 @@ public: virtual void DropReference(); virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate); - virtual nsresult SetCSSDeclaration(nsCSSDeclaration *aDecl); virtual nsresult GetCSSParsingEnvironment(nsIContent* aContent, nsIURI** aBaseURI, nsICSSLoader** aCSSLoader, @@ -74,6 +73,8 @@ public: virtual nsresult GetParent(nsISupports **aParent); protected: + nsresult SetCSSDeclaration(nsCSSDeclaration* aDecl, PRBool aNotify); + nsIHTMLContent *mContent; }; diff --git a/mozilla/content/html/style/src/nsDOMCSSDeclaration.h b/mozilla/content/html/style/src/nsDOMCSSDeclaration.h index 53023862ffe..d8b32f3e2c0 100644 --- a/mozilla/content/html/style/src/nsDOMCSSDeclaration.h +++ b/mozilla/content/html/style/src/nsDOMCSSDeclaration.h @@ -78,9 +78,6 @@ public: virtual void DropReference() = 0; virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate) = 0; - // Note! This will only set the declaration if a style rule already exists - virtual nsresult SetCSSDeclaration(nsCSSDeclaration *aDecl) = 0; - virtual nsresult ParsePropertyValue(const nsAString& aPropName, const nsAString& aPropValue) = 0; virtual nsresult ParseDeclaration(const nsAString& aDecl, diff --git a/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp b/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp index c31d3557fdf..fd327e99836 100644 --- a/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp +++ b/mozilla/content/html/style/src/nsHTMLCSSStyleSheet.cpp @@ -455,7 +455,7 @@ HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData, nsCOMPtr rule; styledContent->GetInlineStyleRule(getter_AddRefs(rule)); if (rule) - aData->mRuleWalker->Forward(rule, PR_TRUE); + aData->mRuleWalker->Forward(rule); } return NS_OK; diff --git a/mozilla/content/shared/public/nsRuleNode.h b/mozilla/content/shared/public/nsRuleNode.h index fe978d1ab8c..5a71a078966 100644 --- a/mozilla/content/shared/public/nsRuleNode.h +++ b/mozilla/content/shared/public/nsRuleNode.h @@ -545,7 +545,7 @@ public: static void CreateRootNode(nsIPresContext* aPresContext, nsRuleNode** aResult); nsresult GetBits(PRInt32 aType, PRUint32* aResult); - nsresult Transition(nsIStyleRule* aRule, PRBool aIsInlineStyle, nsRuleNode** aResult); + nsresult Transition(nsIStyleRule* aRule, nsRuleNode** aResult); nsRuleNode* GetParent() { return mParent; } PRBool IsRoot() { return mParent == nsnull; } nsresult GetRule(nsIStyleRule** aResult) diff --git a/mozilla/content/shared/public/nsRuleWalker.h b/mozilla/content/shared/public/nsRuleWalker.h index 0d73ab21ec3..71fd2e09e33 100644 --- a/mozilla/content/shared/public/nsRuleWalker.h +++ b/mozilla/content/shared/public/nsRuleWalker.h @@ -44,9 +44,9 @@ public: nsRuleNode* GetCurrentNode() { return mCurrent; } void SetCurrentNode(nsRuleNode* aNode) { mCurrent = aNode; } - void Forward(nsIStyleRule* aRule, PRBool aIsInlineStyle = PR_FALSE) { + void Forward(nsIStyleRule* aRule) { nsRuleNode* next; - mCurrent->Transition(aRule, aIsInlineStyle, &next); + mCurrent->Transition(aRule, &next); mCurrent = next; } diff --git a/mozilla/layout/base/nsCSSFrameConstructor.cpp b/mozilla/layout/base/nsCSSFrameConstructor.cpp index 5723e64dc8d..f4015781803 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/base/nsCSSFrameConstructor.cpp @@ -10677,59 +10677,6 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, #endif // INCLUDE_XUL - // check for inline style. we need to clear the data at the style - // context's rule node whenever the inline style property changes. - - nsRefPtr styleContext; - nsCOMPtr rule; - PRBool inlineStyle = PR_FALSE; - if (aAttribute == nsHTMLAtoms::style) { - nsCOMPtr scontent(do_QueryInterface(aContent)); - scontent->GetInlineStyleRule(getter_AddRefs(rule)); - if (rule) { - inlineStyle = PR_TRUE; - - // This style rule exists and we need to blow away any computed - // data that this rule cached in the rule tree. - if (primaryStyleFrame) { - styleContext = primaryStyleFrame->GetStyleContext(); - } else { - // We might be in the undisplayed map. Retrieve the style context from there. - nsCOMPtr frameManager; - shell->GetFrameManager(getter_AddRefs(frameManager)); - styleContext = frameManager->GetUndisplayedContent(aContent); -#ifdef DEBUG - if (!styleContext) { - nsCOMPtr parent; - aContent->GetParent(*getter_AddRefs(parent)); - if (parent) { - nsIFrame* parentFrame; - shell->GetPrimaryFrameFor(parent, &parentFrame); - NS_ASSERTION(!parentFrame, - "parent frame but no child frame or undisplayed entry"); - } - } -#endif - } - } - } - - // first see if we need to manage the style system: - // inlineStyle changes require us to clear out style data associated with the style attribute - // NOTE: for reframe, it happens after the old frames have been destroyed, not here, otherwise - // we cannot get to the old style information for the old frame, and cannot correctly - // deal with positioned frames or floaters (see bug 118415) - this is done in - // RecreateFramesForContent, which is called for a reframe - if (inlineStyle && - (reconstruct || restyle) && - !reframe) { - nsCOMPtr set; - shell->GetStyleSet(getter_AddRefs(set)); - // XXXldb If |styleContext| is null, wouldn't it be faster to pass - // in something to tell it that this change is for inline style? - set->ClearStyleData(aPresContext, rule, styleContext); - } - // See if we have appearance information for a theme. if (primaryFrame) { const nsStyleDisplay* disp; @@ -10748,13 +10695,14 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, } // apply changes - if (primaryFrame && (aHint & nsChangeHint_AttrChange) && !(aHint & ~(nsChangeHint_AttrChange))) + if (primaryFrame && (aHint & nsChangeHint_AttrChange) && !(aHint & ~(nsChangeHint_AttrChange))) { result = primaryFrame->AttributeChanged(aPresContext, aContent, aNameSpaceID, aAttribute, aModType, aHint); + } else if (reconstruct) { result = ReconstructDocElementHierarchy(aPresContext); } else if (reframe) { - result = RecreateFramesForContent(aPresContext, aContent, inlineStyle, rule, styleContext); + result = RecreateFramesForContent(aPresContext, aContent); } else if (restyle) { // If there is no frame then there is no point in re-styling it, @@ -10807,7 +10755,7 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, ProcessRestyledFrames(changeList, aPresContext); } else { // no frame now, possibly genetate one with new style data - result = RecreateFramesForContent(aPresContext, aContent, inlineStyle, rule, styleContext); + result = RecreateFramesForContent(aPresContext, aContent); } } @@ -10839,7 +10787,7 @@ nsCSSFrameConstructor::StyleRuleChanged(nsIPresContext* aPresContext, if (restyle) { nsCOMPtr set; shell->GetStyleSet(getter_AddRefs(set)); - set->ClearStyleData(aPresContext, aStyleRule, nsnull); + set->ClearStyleData(aPresContext, aStyleRule); } if (reframe) { @@ -12064,9 +12012,7 @@ nsCSSFrameConstructor::CaptureStateFor(nsIPresContext* aPresContext, nsresult nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, - nsIContent* aContent, PRBool aInlineStyle, - nsIStyleRule* aInlineStyleRule, - nsStyleContext* aStyleContext) + nsIContent* aContent) { // Is the frame `special'? If so, we need to reframe the containing // block *here*, rather than trying to remove and re-insert the @@ -12123,17 +12069,6 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, // attribute change occurred. rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE); - // Now that the old frame is gone (and has stopped depending on obsolete style - // data), we need to blow away our style information if this reframe happened as - // a result of an inline style attribute changing. - if (aInlineStyle) { - nsCOMPtr set; - shell->GetStyleSet(getter_AddRefs(set)); - // XXXldb If |aStyleContext| is null, wouldn't it be faster to pass - // in something to tell it that this change is for inline style? - set->ClearStyleData(aPresContext, aInlineStyleRule, aStyleContext); - } - if (NS_SUCCEEDED(rv)) { // Now, recreate the frames associated with this content object. rv = ContentInserted(aPresContext, container, aContent, indexInContainer, mTempFrameTreeState, PR_FALSE); diff --git a/mozilla/layout/base/nsCSSFrameConstructor.h b/mozilla/layout/base/nsCSSFrameConstructor.h index 58dd1b2b4a6..47780b79b0c 100644 --- a/mozilla/layout/base/nsCSSFrameConstructor.h +++ b/mozilla/layout/base/nsCSSFrameConstructor.h @@ -770,10 +770,7 @@ protected: PRBool UseXBLForms(); nsresult RecreateFramesForContent(nsIPresContext* aPresContext, - nsIContent* aContent, - PRBool aInlineStyle = PR_FALSE, - nsIStyleRule* aRule = nsnull, - nsStyleContext* aContext = nsnull); + nsIContent* aContent); nsresult RecreateFramesOnAttributeChange(nsIPresContext* aPresContext, nsIContent* aContent, diff --git a/mozilla/layout/base/nsPresContext.cpp b/mozilla/layout/base/nsPresContext.cpp index d16fafa0b1e..701b0fdfa1b 100644 --- a/mozilla/layout/base/nsPresContext.cpp +++ b/mozilla/layout/base/nsPresContext.cpp @@ -589,7 +589,7 @@ nsPresContext::ClearStyleDataAndReflow() // Clear out all our style data. nsCOMPtr set; mShell->GetStyleSet(getter_AddRefs(set)); - set->ClearStyleData(this, nsnull, nsnull); + set->ClearStyleData(this, nsnull); // 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 0d544964b85..feb47f76476 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -5667,7 +5667,7 @@ PresShell::BidiStyleChangeReflow() nsIFrame* rootFrame; mFrameManager->GetRootFrame(&rootFrame); if (rootFrame) { - mStyleSet->ClearStyleData(mPresContext, nsnull, nsnull); + mStyleSet->ClearStyleData(mPresContext, nsnull); ReconstructFrames(); } return NS_OK; diff --git a/mozilla/layout/base/public/nsIStyleSet.h b/mozilla/layout/base/public/nsIStyleSet.h index c5222144fdf..f371fa2b8d6 100644 --- a/mozilla/layout/base/public/nsIStyleSet.h +++ b/mozilla/layout/base/public/nsIStyleSet.h @@ -111,11 +111,6 @@ public: virtual nsresult GetRuleTree(nsRuleNode** aResult) = 0; virtual nsresult ClearCachedDataInRuleTree(nsIStyleRule* aRule) = 0; - // This method is used to add a mapping from rule to rule node so that all the rule nodes - // in use for a given rule can be accessed efficiently. This is currently only used - // for inline style rules in order to conserve footprint. - virtual nsresult AddRuleNodeMapping(nsRuleNode* aRuleNode) = 0; - // The following two methods can be used to tear down and reconstruct a rule tree. The idea // is to first call BeginRuleTreeReconstruct, which will set aside the old rule // tree. The entire frame tree should then have ReResolveStyleContext @@ -138,10 +133,7 @@ public: // 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. // - // |aContext| provides an additional hint that a specific style context has changed, and - // that the entire rule tree need not be searched for occurrences of |aRule|. It is - // only specified in the inline style case, i.e., when the inline style attribute changes. - virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsStyleContext* aContext) = 0; + virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule) = 0; // enable / disable the Quirk style sheet: // returns NS_FAILURE if none is found, otherwise NS_OK diff --git a/mozilla/layout/base/src/nsPresContext.cpp b/mozilla/layout/base/src/nsPresContext.cpp index d16fafa0b1e..701b0fdfa1b 100644 --- a/mozilla/layout/base/src/nsPresContext.cpp +++ b/mozilla/layout/base/src/nsPresContext.cpp @@ -589,7 +589,7 @@ nsPresContext::ClearStyleDataAndReflow() // Clear out all our style data. nsCOMPtr set; mShell->GetStyleSet(getter_AddRefs(set)); - set->ClearStyleData(this, nsnull, nsnull); + set->ClearStyleData(this, nsnull); // 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 0d544964b85..feb47f76476 100644 --- a/mozilla/layout/html/base/src/nsPresShell.cpp +++ b/mozilla/layout/html/base/src/nsPresShell.cpp @@ -5667,7 +5667,7 @@ PresShell::BidiStyleChangeReflow() nsIFrame* rootFrame; mFrameManager->GetRootFrame(&rootFrame); if (rootFrame) { - mStyleSet->ClearStyleData(mPresContext, nsnull, nsnull); + mStyleSet->ClearStyleData(mPresContext, nsnull); ReconstructFrames(); } return NS_OK; diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp index 5723e64dc8d..f4015781803 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.cpp @@ -10677,59 +10677,6 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, #endif // INCLUDE_XUL - // check for inline style. we need to clear the data at the style - // context's rule node whenever the inline style property changes. - - nsRefPtr styleContext; - nsCOMPtr rule; - PRBool inlineStyle = PR_FALSE; - if (aAttribute == nsHTMLAtoms::style) { - nsCOMPtr scontent(do_QueryInterface(aContent)); - scontent->GetInlineStyleRule(getter_AddRefs(rule)); - if (rule) { - inlineStyle = PR_TRUE; - - // This style rule exists and we need to blow away any computed - // data that this rule cached in the rule tree. - if (primaryStyleFrame) { - styleContext = primaryStyleFrame->GetStyleContext(); - } else { - // We might be in the undisplayed map. Retrieve the style context from there. - nsCOMPtr frameManager; - shell->GetFrameManager(getter_AddRefs(frameManager)); - styleContext = frameManager->GetUndisplayedContent(aContent); -#ifdef DEBUG - if (!styleContext) { - nsCOMPtr parent; - aContent->GetParent(*getter_AddRefs(parent)); - if (parent) { - nsIFrame* parentFrame; - shell->GetPrimaryFrameFor(parent, &parentFrame); - NS_ASSERTION(!parentFrame, - "parent frame but no child frame or undisplayed entry"); - } - } -#endif - } - } - } - - // first see if we need to manage the style system: - // inlineStyle changes require us to clear out style data associated with the style attribute - // NOTE: for reframe, it happens after the old frames have been destroyed, not here, otherwise - // we cannot get to the old style information for the old frame, and cannot correctly - // deal with positioned frames or floaters (see bug 118415) - this is done in - // RecreateFramesForContent, which is called for a reframe - if (inlineStyle && - (reconstruct || restyle) && - !reframe) { - nsCOMPtr set; - shell->GetStyleSet(getter_AddRefs(set)); - // XXXldb If |styleContext| is null, wouldn't it be faster to pass - // in something to tell it that this change is for inline style? - set->ClearStyleData(aPresContext, rule, styleContext); - } - // See if we have appearance information for a theme. if (primaryFrame) { const nsStyleDisplay* disp; @@ -10748,13 +10695,14 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, } // apply changes - if (primaryFrame && (aHint & nsChangeHint_AttrChange) && !(aHint & ~(nsChangeHint_AttrChange))) + if (primaryFrame && (aHint & nsChangeHint_AttrChange) && !(aHint & ~(nsChangeHint_AttrChange))) { result = primaryFrame->AttributeChanged(aPresContext, aContent, aNameSpaceID, aAttribute, aModType, aHint); + } else if (reconstruct) { result = ReconstructDocElementHierarchy(aPresContext); } else if (reframe) { - result = RecreateFramesForContent(aPresContext, aContent, inlineStyle, rule, styleContext); + result = RecreateFramesForContent(aPresContext, aContent); } else if (restyle) { // If there is no frame then there is no point in re-styling it, @@ -10807,7 +10755,7 @@ nsCSSFrameConstructor::AttributeChanged(nsIPresContext* aPresContext, ProcessRestyledFrames(changeList, aPresContext); } else { // no frame now, possibly genetate one with new style data - result = RecreateFramesForContent(aPresContext, aContent, inlineStyle, rule, styleContext); + result = RecreateFramesForContent(aPresContext, aContent); } } @@ -10839,7 +10787,7 @@ nsCSSFrameConstructor::StyleRuleChanged(nsIPresContext* aPresContext, if (restyle) { nsCOMPtr set; shell->GetStyleSet(getter_AddRefs(set)); - set->ClearStyleData(aPresContext, aStyleRule, nsnull); + set->ClearStyleData(aPresContext, aStyleRule); } if (reframe) { @@ -12064,9 +12012,7 @@ nsCSSFrameConstructor::CaptureStateFor(nsIPresContext* aPresContext, nsresult nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, - nsIContent* aContent, PRBool aInlineStyle, - nsIStyleRule* aInlineStyleRule, - nsStyleContext* aStyleContext) + nsIContent* aContent) { // Is the frame `special'? If so, we need to reframe the containing // block *here*, rather than trying to remove and re-insert the @@ -12123,17 +12069,6 @@ nsCSSFrameConstructor::RecreateFramesForContent(nsIPresContext* aPresContext, // attribute change occurred. rv = ContentRemoved(aPresContext, container, aContent, indexInContainer, PR_FALSE); - // Now that the old frame is gone (and has stopped depending on obsolete style - // data), we need to blow away our style information if this reframe happened as - // a result of an inline style attribute changing. - if (aInlineStyle) { - nsCOMPtr set; - shell->GetStyleSet(getter_AddRefs(set)); - // XXXldb If |aStyleContext| is null, wouldn't it be faster to pass - // in something to tell it that this change is for inline style? - set->ClearStyleData(aPresContext, aInlineStyleRule, aStyleContext); - } - if (NS_SUCCEEDED(rv)) { // Now, recreate the frames associated with this content object. rv = ContentInserted(aPresContext, container, aContent, indexInContainer, mTempFrameTreeState, PR_FALSE); diff --git a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h index 58dd1b2b4a6..47780b79b0c 100644 --- a/mozilla/layout/html/style/src/nsCSSFrameConstructor.h +++ b/mozilla/layout/html/style/src/nsCSSFrameConstructor.h @@ -770,10 +770,7 @@ protected: PRBool UseXBLForms(); nsresult RecreateFramesForContent(nsIPresContext* aPresContext, - nsIContent* aContent, - PRBool aInlineStyle = PR_FALSE, - nsIStyleRule* aRule = nsnull, - nsStyleContext* aContext = nsnull); + nsIContent* aContent); nsresult RecreateFramesOnAttributeChange(nsIPresContext* aPresContext, nsIContent* aContent, diff --git a/mozilla/layout/style/nsCSSStyleRule.cpp b/mozilla/layout/style/nsCSSStyleRule.cpp index b4a944a6835..0246fc077ad 100644 --- a/mozilla/layout/style/nsCSSStyleRule.cpp +++ b/mozilla/layout/style/nsCSSStyleRule.cpp @@ -901,7 +901,6 @@ public: virtual void DropReference(void); virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate); - virtual nsresult SetCSSDeclaration(nsCSSDeclaration *aDecl); virtual nsresult GetCSSParsingEnvironment(nsICSSStyleRule* aRule, nsICSSStyleSheet** aSheet, nsIDocument** aDocument, @@ -1006,16 +1005,6 @@ DOMCSSDeclarationImpl::GetCSSDeclaration(nsCSSDeclaration **aDecl, return NS_OK; } -nsresult -DOMCSSDeclarationImpl::SetCSSDeclaration(nsCSSDeclaration *aDecl) -{ - if (mRule) { - mRule->SetDeclaration(aDecl); - } - - return NS_OK; -} - /* * 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, @@ -1152,10 +1141,7 @@ DOMCSSDeclarationImpl::ParseDeclaration(const nsAString& aDecl, result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, aParseOnlyOneDecl, &hint); - if (result == NS_CSS_PARSER_DROP_DECLARATION) { - SetCSSDeclaration(declClone); - result = NS_OK; - } else if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(result)) { if (cssSheet) { cssSheet->SetModified(PR_TRUE); } diff --git a/mozilla/layout/style/nsDOMCSSAttrDeclaration.cpp b/mozilla/layout/style/nsDOMCSSAttrDeclaration.cpp index 0a583fda8ac..df88034c175 100644 --- a/mozilla/layout/style/nsDOMCSSAttrDeclaration.cpp +++ b/mozilla/layout/style/nsDOMCSSAttrDeclaration.cpp @@ -73,42 +73,16 @@ nsDOMCSSAttributeDeclaration::RemoveProperty(const nsAString& aPropertyName, nsAString& aReturn) { nsCSSDeclaration* decl; - nsresult rv = GetCSSDeclaration(&decl, PR_TRUE); - - if (NS_SUCCEEDED(rv) && decl && mContent) { - nsCOMPtr doc; - mContent->GetDocument(*getter_AddRefs(doc)); - - if (doc) { - doc->BeginUpdate(); - - doc->AttributeWillChange(mContent, kNameSpaceID_None, - nsHTMLAtoms::style); - } - - nsChangeHint hint = NS_STYLE_HINT_NONE; + nsresult rv = GetCSSDeclaration(&decl, PR_FALSE); + if (NS_SUCCEEDED(rv) && decl) { nsCSSProperty prop = nsCSSProps::LookupProperty(aPropertyName); nsCSSValue val; rv = decl->RemoveProperty(prop, val); if (NS_SUCCEEDED(rv)) { - // We pass in eCSSProperty_UNKNOWN here so that we don't get the - // property name in the return string. - val.ToString(aReturn, eCSSProperty_UNKNOWN); - hint = 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 (doc) { - doc->AttributeChanged(mContent, kNameSpaceID_None, nsHTMLAtoms::style, - nsIDOMMutationEvent::MODIFICATION, - hint); - doc->EndUpdate(); + rv = SetCSSDeclaration(decl, PR_TRUE); } } @@ -121,6 +95,23 @@ nsDOMCSSAttributeDeclaration::DropReference() mContent = nsnull; } +nsresult +nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration* aDecl, + PRBool aNotify) +{ + NS_ASSERTION(mContent, "Must have content node to set the decl!"); + + nsCOMPtr cssRule; + nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsCSSSelector()); + NS_ENSURE_SUCCESS(rv, rv); + + cssRule->SetDeclaration(aDecl); + cssRule->SetWeight(PR_INT32_MAX); + return mContent->SetHTMLAttribute(nsHTMLAtoms::style, + nsHTMLValue(cssRule), + aNotify); +} + nsresult nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate) @@ -130,8 +121,9 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, *aDecl = nsnull; if (mContent) { nsHTMLValue val; - mContent->GetHTMLAttribute(nsHTMLAtoms::style, val); - if (eHTMLUnit_ISupports == val.GetUnit()) { + result = mContent->GetHTMLAttribute(nsHTMLAtoms::style, val); + if (result == NS_CONTENT_ATTR_HAS_VALUE && + eHTMLUnit_ISupports == val.GetUnit()) { nsCOMPtr rule = val.GetISupportsValue(); nsCOMPtr cssRule = do_QueryInterface(rule, &result); if (cssRule) { @@ -140,17 +132,9 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, } else if (aAllocate) { result = NS_NewCSSDeclaration(aDecl); - if (NS_OK == result) { - nsCOMPtr cssRule; - result = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsCSSSelector()); - if (NS_OK == result) { - cssRule->SetDeclaration(*aDecl); - cssRule->SetWeight(0x7fffffff); - result = mContent->SetHTMLAttribute(nsHTMLAtoms::style, - nsHTMLValue(cssRule), - PR_FALSE); - } - else { + if (NS_SUCCEEDED(result)) { + result = SetCSSDeclaration(*aDecl, PR_FALSE); + if (NS_FAILED(result)) { (*aDecl)->RuleAbort(); *aDecl = nsnull; } @@ -161,26 +145,6 @@ nsDOMCSSAttributeDeclaration::GetCSSDeclaration(nsCSSDeclaration **aDecl, return result; } -nsresult -nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration *aDecl) -{ - nsresult result = NS_OK; - - if (mContent) { - nsHTMLValue val; - mContent->GetHTMLAttribute(nsHTMLAtoms::style, val); - if (eHTMLUnit_ISupports == val.GetUnit()) { - nsCOMPtr rule = val.GetISupportsValue(); - nsCOMPtr cssRule = do_QueryInterface(rule, &result); - if (cssRule) { - cssRule->SetDeclaration(aDecl); - } - } - } - - return result; -} - /* * 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 @@ -247,12 +211,6 @@ nsDOMCSSAttributeDeclaration::ParsePropertyValue(const nsAString& aPropName, nsCOMPtr cssLoader; nsCOMPtr cssParser; nsCOMPtr baseURI; - nsCOMPtr doc; - - result = mContent->GetDocument(*getter_AddRefs(doc)); - if (NS_FAILED(result)) { - return result; - } result = GetCSSParsingEnvironment(mContent, getter_AddRefs(baseURI), @@ -262,24 +220,18 @@ nsDOMCSSAttributeDeclaration::ParsePropertyValue(const nsAString& aPropName, return result; } - nsChangeHint hint = NS_STYLE_HINT_NONE; - if (doc) { - doc->BeginUpdate(); - doc->AttributeWillChange(mContent, kNameSpaceID_None, nsHTMLAtoms::style); - } - - result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, &hint); - if (doc) { - doc->AttributeChanged(mContent, kNameSpaceID_None, nsHTMLAtoms::style, - nsIDOMMutationEvent::MODIFICATION, hint); - doc->EndUpdate(); + nsChangeHint uselessHint = NS_STYLE_HINT_NONE; + result = cssParser->ParseProperty(aPropName, aPropValue, baseURI, decl, + &uselessHint); + if (NS_SUCCEEDED(result)) { + result = SetCSSDeclaration(decl, PR_TRUE); } if (cssLoader) { cssLoader->RecycleParser(cssParser); } - return NS_OK; + return result; } nsresult @@ -290,70 +242,51 @@ nsDOMCSSAttributeDeclaration::ParseDeclaration(const nsAString& aDecl, nsCSSDeclaration* decl; nsresult result = GetCSSDeclaration(&decl, PR_TRUE); - if (decl) { - nsCOMPtr cssLoader; - nsCOMPtr cssParser; - nsCOMPtr baseURI; - nsCOMPtr doc; + if (!decl) { + return result; + } - result = mContent->GetDocument(*getter_AddRefs(doc)); - if (NS_FAILED(result)) { - 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; + } + + if (aClearOldDecl) { + // This should be done with decl->Clear() once such a method exists. + nsAutoString propName; + PRUint32 count, i; + + count = decl->Count(); + + for (i = 0; i < count; i++) { + decl->GetNthProperty(0, propName); + + nsCSSProperty prop = nsCSSProps::LookupProperty(propName); + nsCSSValue val; + + decl->RemoveProperty(prop, val); } - result = GetCSSParsingEnvironment(mContent, - getter_AddRefs(baseURI), - getter_AddRefs(cssLoader), - getter_AddRefs(cssParser)); - - if (NS_SUCCEEDED(result)) { - nsChangeHint hint = NS_STYLE_HINT_NONE; - if (doc) { - doc->BeginUpdate(); - - doc->AttributeWillChange(mContent, kNameSpaceID_None, - nsHTMLAtoms::style); - } - nsCSSDeclaration* declClone = decl->Clone(); - - if (aClearOldDecl) { - hint = decl->GetStyleImpact(); - // This should be done with decl->Clear() once such a method exists. - nsAutoString propName; - PRUint32 count, i; - - count = decl->Count(); - - for (i = 0; i < count; i++) { - decl->GetNthProperty(0, propName); - - nsCSSProperty prop = nsCSSProps::LookupProperty(propName); - nsCSSValue val; - - decl->RemoveProperty(prop, val); - } - } + } - nsChangeHint newHint = NS_STYLE_HINT_NONE; - result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, - aParseOnlyOneDecl, &newHint); - NS_UpdateHint(hint, newHint); - - if (result == NS_CSS_PARSER_DROP_DECLARATION) { - SetCSSDeclaration(declClone); - result = NS_OK; - } - if (doc) { - if (NS_SUCCEEDED(result) && result != NS_CSS_PARSER_DROP_DECLARATION) { - doc->AttributeChanged(mContent, kNameSpaceID_None, - nsHTMLAtoms::style, - nsIDOMMutationEvent::MODIFICATION, hint); - } - doc->EndUpdate(); - } - if (cssLoader) { - cssLoader->RecycleParser(cssParser); - } - } + nsChangeHint uselessHint = NS_STYLE_HINT_NONE; + result = cssParser->ParseAndAppendDeclaration(aDecl, baseURI, decl, + aParseOnlyOneDecl, + &uselessHint); + + if (NS_SUCCEEDED(result)) { + result = SetCSSDeclaration(decl, PR_TRUE); + } + + if (cssLoader) { + cssLoader->RecycleParser(cssParser); } return result; diff --git a/mozilla/layout/style/nsDOMCSSAttrDeclaration.h b/mozilla/layout/style/nsDOMCSSAttrDeclaration.h index 14ae2e5b3b8..d080f2c0be8 100644 --- a/mozilla/layout/style/nsDOMCSSAttrDeclaration.h +++ b/mozilla/layout/style/nsDOMCSSAttrDeclaration.h @@ -61,7 +61,6 @@ public: virtual void DropReference(); virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate); - virtual nsresult SetCSSDeclaration(nsCSSDeclaration *aDecl); virtual nsresult GetCSSParsingEnvironment(nsIContent* aContent, nsIURI** aBaseURI, nsICSSLoader** aCSSLoader, @@ -74,6 +73,8 @@ public: virtual nsresult GetParent(nsISupports **aParent); protected: + nsresult SetCSSDeclaration(nsCSSDeclaration* aDecl, PRBool aNotify); + nsIHTMLContent *mContent; }; diff --git a/mozilla/layout/style/nsDOMCSSDeclaration.h b/mozilla/layout/style/nsDOMCSSDeclaration.h index 53023862ffe..d8b32f3e2c0 100644 --- a/mozilla/layout/style/nsDOMCSSDeclaration.h +++ b/mozilla/layout/style/nsDOMCSSDeclaration.h @@ -78,9 +78,6 @@ public: virtual void DropReference() = 0; virtual nsresult GetCSSDeclaration(nsCSSDeclaration **aDecl, PRBool aAllocate) = 0; - // Note! This will only set the declaration if a style rule already exists - virtual nsresult SetCSSDeclaration(nsCSSDeclaration *aDecl) = 0; - virtual nsresult ParsePropertyValue(const nsAString& aPropName, const nsAString& aPropValue) = 0; virtual nsresult ParseDeclaration(const nsAString& aDecl, diff --git a/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp b/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp index c31d3557fdf..fd327e99836 100644 --- a/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/mozilla/layout/style/nsHTMLCSSStyleSheet.cpp @@ -455,7 +455,7 @@ HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData, nsCOMPtr rule; styledContent->GetInlineStyleRule(getter_AddRefs(rule)); if (rule) - aData->mRuleWalker->Forward(rule, PR_TRUE); + aData->mRuleWalker->Forward(rule); } return NS_OK; diff --git a/mozilla/layout/style/nsRuleNode.cpp b/mozilla/layout/style/nsRuleNode.cpp index 270f7bc6cef..689efb56739 100644 --- a/mozilla/layout/style/nsRuleNode.cpp +++ b/mozilla/layout/style/nsRuleNode.cpp @@ -470,7 +470,7 @@ nsRuleNode::GetBits(PRInt32 aType, PRUint32* aResult) } nsresult -nsRuleNode::Transition(nsIStyleRule* aRule, PRBool aIsInlineStyle, nsRuleNode** aResult) +nsRuleNode::Transition(nsIStyleRule* aRule, nsRuleNode** aResult) { nsRuleNode* next = nsnull; @@ -513,21 +513,7 @@ nsRuleNode::Transition(nsIStyleRule* aRule, PRBool aIsInlineStyle, nsRuleNode** SetChildrenList(new (mPresContext) nsRuleList(next, ChildrenList())); createdNode = PR_TRUE; } - - if (aIsInlineStyle && createdNode) { - // We just made a new rule node for an inline style rule (e.g., for - // the style attribute on an HTML, SVG, or XUL element). In order to - // fix bug 99344, we have to maintain a mapping from inline style rules - // to all the rule nodes in a rule tree that correspond to the inline - // style rule. - // Obtain our style set and then add this rule node to our mapping. - nsCOMPtr shell; - mPresContext->GetShell(getter_AddRefs(shell)); - nsCOMPtr styleSet; - shell->GetStyleSet(getter_AddRefs(styleSet)); - styleSet->AddRuleNodeMapping(next); - } - + *aResult = next; return NS_OK; } diff --git a/mozilla/layout/style/nsRuleNode.h b/mozilla/layout/style/nsRuleNode.h index fe978d1ab8c..5a71a078966 100644 --- a/mozilla/layout/style/nsRuleNode.h +++ b/mozilla/layout/style/nsRuleNode.h @@ -545,7 +545,7 @@ public: static void CreateRootNode(nsIPresContext* aPresContext, nsRuleNode** aResult); nsresult GetBits(PRInt32 aType, PRUint32* aResult); - nsresult Transition(nsIStyleRule* aRule, PRBool aIsInlineStyle, nsRuleNode** aResult); + nsresult Transition(nsIStyleRule* aRule, nsRuleNode** aResult); nsRuleNode* GetParent() { return mParent; } PRBool IsRoot() { return mParent == nsnull; } nsresult GetRule(nsIStyleRule** aResult) diff --git a/mozilla/layout/style/nsRuleWalker.h b/mozilla/layout/style/nsRuleWalker.h index 0d73ab21ec3..71fd2e09e33 100644 --- a/mozilla/layout/style/nsRuleWalker.h +++ b/mozilla/layout/style/nsRuleWalker.h @@ -44,9 +44,9 @@ public: nsRuleNode* GetCurrentNode() { return mCurrent; } void SetCurrentNode(nsRuleNode* aNode) { mCurrent = aNode; } - void Forward(nsIStyleRule* aRule, PRBool aIsInlineStyle = PR_FALSE) { + void Forward(nsIStyleRule* aRule) { nsRuleNode* next; - mCurrent->Transition(aRule, aIsInlineStyle, &next); + mCurrent->Transition(aRule, &next); mCurrent = next; } diff --git a/mozilla/layout/style/nsStyleSet.cpp b/mozilla/layout/style/nsStyleSet.cpp index c70b97619f8..5f4aaa7b1e1 100644 --- a/mozilla/layout/style/nsStyleSet.cpp +++ b/mozilla/layout/style/nsStyleSet.cpp @@ -189,9 +189,7 @@ public: virtual nsresult GetRuleTree(nsRuleNode** aResult); virtual nsresult ClearCachedDataInRuleTree(nsIStyleRule* aRule); - virtual nsresult AddRuleNodeMapping(nsRuleNode* aRuleNode); - - virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsStyleContext* aContext); + virtual nsresult ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule); virtual nsresult GetStyleFrameConstruction(nsIStyleFrameConstruction** aResult) { *aResult = mFrameConstructor; @@ -369,7 +367,6 @@ protected: nsRuleNode* mOldRuleTree; // Used during rule tree reconstruction. nsRuleWalker* mRuleWalker; // This is an instance of a rule walker that can be used // to navigate through our tree. - nsHashtable mRuleMappings; // A hashtable from rules to rule node lists. MOZ_TIMER_DECLARE(mStyleResolutionWatch) @@ -387,8 +384,7 @@ StyleSetImpl::StyleSetImpl() mQuirkStyleSheet(nsnull), mRuleTree(nsnull), mOldRuleTree(nsnull), - mRuleWalker(nsnull), - mRuleMappings(32) + mRuleWalker(nsnull) #ifdef MOZ_PERF_METRICS ,mTimerEnabled(PR_FALSE) #endif @@ -1361,9 +1357,6 @@ PRBool PR_CALLBACK DeleteRuleNodeLists(nsHashKey* aKey, void* aData, void* aClos NS_IMETHODIMP StyleSetImpl::Shutdown() { - mRuleMappings.Enumerate(DeleteRuleNodeLists); - mRuleMappings.Reset(); - delete mRuleWalker; if (mRuleTree) { @@ -1380,17 +1373,6 @@ StyleSetImpl::GetRuleTree(nsRuleNode** aResult) return NS_OK; } -nsresult -StyleSetImpl::AddRuleNodeMapping(nsRuleNode* aRuleNode) -{ - nsVoidKey key(aRuleNode->Rule()); - nsRuleNodeList* ruleList = - new (aRuleNode->PresContext()) nsRuleNodeList(aRuleNode, - NS_STATIC_CAST(nsRuleNodeList*, mRuleMappings.Get(&key))); - mRuleMappings.Put(&key, ruleList); - return NS_OK; -} - nsresult StyleSetImpl::BeginRuleTreeReconstruct() { @@ -1398,8 +1380,6 @@ StyleSetImpl::BeginRuleTreeReconstruct() mRuleWalker = nsnull; mOldRuleTree = mRuleTree; mRuleTree = nsnull; - mRuleMappings.Enumerate(DeleteRuleNodeLists); - mRuleMappings.Reset(); return NS_OK; } @@ -1422,63 +1402,30 @@ StyleSetImpl::ClearCachedDataInRuleTree(nsIStyleRule* aInlineStyleRule) } nsresult -StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule, nsStyleContext* aContext) +StyleSetImpl::ClearStyleData(nsIPresContext* aPresContext, nsIStyleRule* aRule) { - // XXXdwh. If we're willing to *really* optimize this - // invalidation, we could only invalidate the struct data - // that actually changed. For example, if someone changes - // style.left, we really only need to blow away cached - // data in the position struct. - if (aContext) { - // |aRule| should never be null, but we'll sanity check it just in case. - if (aRule) { - // Obtain our rule node list and clear out the cached data in all rule nodes - // that correspond to this rule. See bug 99344 for more details as to how - // inline style rules can end up with multiple rule nodes in a rule tree. - nsVoidKey key(aRule); - nsRuleNodeList* ruleList = NS_STATIC_CAST(nsRuleNodeList*, mRuleMappings.Get(&key)); - for ( ; ruleList; ruleList = ruleList->mNext) - ruleList->mRuleNode->ClearCachedData(aRule); - } - - // XXXdwh I'm just being paranoid here. Also clear out the data starting at the style - // context's rule node. This really should always be done in the for loop above, - // but I'm going to leave this here just in case (for now). - nsRuleNode* ruleNode; - aContext->GetRuleNode(&ruleNode); - ruleNode->ClearCachedData(aRule); - - // XXX We need to clear style data here in case there's a style context - // that inherits a struct from its parent where the parent uses data - // that's cached on the rule node. Otherwise we could crash while - // doing checks comparing old data to new data during reresolution. - // This could make some of those checks incorrect. - aContext->ClearStyleData(aPresContext, nsnull); - } - else { - // 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); - } + // 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); } return NS_OK;