diff --git a/content/html/style/src/nsCSSParser.cpp b/content/html/style/src/nsCSSParser.cpp
index 4ce1045e890b..95cb6273eaad 100644
--- a/content/html/style/src/nsCSSParser.cpp
+++ b/content/html/style/src/nsCSSParser.cpp
@@ -89,7 +89,7 @@ struct SelectorList {
SelectorList(void);
~SelectorList(void);
- void AddSelector(const nsCSSSelector& aSelector);
+ void AddSelector(nsCSSSelector* aSelector);
#ifdef NS_DEBUG
void Dump(void);
@@ -121,13 +121,13 @@ SelectorList::~SelectorList()
}
}
-void SelectorList::AddSelector(const nsCSSSelector& aSelector)
+// assumes ownership of the selector!
+// Do not add stack-based nsCSSSelector here!
+void SelectorList::AddSelector(nsCSSSelector* aSelector)
{ // prepend to list
- nsCSSSelector* newSel = new nsCSSSelector(aSelector);
- if (nsnull != newSel) {
- newSel->mNext = mSelectors;
- mSelectors = newSel;
- }
+ NS_ASSERTION(aSelector->mNext == nsnull, "are you sure this is a fresh selector?");
+ aSelector->mNext = mSelectors;
+ mSelectors = aSelector;
}
@@ -1619,8 +1619,12 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
PRInt32 weight = 0;
PRBool havePseudoElement = PR_FALSE;
for (;;) {
- nsCSSSelector selector;
- if (! ParseSelector(aErrorCode, selector)) {
+ nsCSSSelector* headSelector = new nsCSSSelector;
+ if (!headSelector) {
+ aErrorCode = NS_ERROR_OUT_OF_MEMORY;
+ return PR_FALSE;
+ }
+ if (! ParseSelector(aErrorCode, *headSelector)) {
break;
}
if (nsnull == list) {
@@ -1630,52 +1634,66 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
return PR_FALSE;
}
}
- list->AddSelector(selector);
- nsCSSSelector* listSel = list->mSelectors;
+
+ list->AddSelector(headSelector);
+
+ // from here on out, we maintain headSelector as the first
+ // non-pseudo element
// pull out pseudo elements here
nsAtomStringList* prevList = nsnull;
- nsAtomStringList* pseudoClassList = listSel->mPseudoClassList;
+ nsAtomStringList* pseudoClassList = headSelector->mPseudoClassList;
while (nsnull != pseudoClassList) {
if (! IsPseudoClass(pseudoClassList->mAtom)) {
havePseudoElement = PR_TRUE;
- if (IsSinglePseudoClass(*listSel)) { // convert to pseudo element selector
+ if (IsSinglePseudoClass(*headSelector)) { // convert to pseudo element selector
nsIAtom* pseudoElement = pseudoClassList->mAtom; // steal ref count
pseudoClassList->mAtom = nsnull;
- listSel->Reset();
- if (listSel->mNext) {// more to the selector
- listSel->mOperator = PRUnichar('>');
- nsCSSSelector empty;
- list->AddSelector(empty); // leave a blank (universal) selector in the middle
- listSel = list->mSelectors; // use the new one for the pseudo
+ headSelector->Reset();
+ if (headSelector->mNext) {// more to the selector
+ headSelector->mOperator = PRUnichar('>');
+ headSelector = new nsCSSSelector;
+ if (!headSelector) {
+ aErrorCode = NS_ERROR_OUT_OF_MEMORY;
+ return PR_FALSE;
+ }
+
+ // leave a blank (universal) selector in the middle
+ list->AddSelector(headSelector);
}
- listSel->mTag = pseudoElement;
+ headSelector->mTag = pseudoElement;
}
else { // append new pseudo element selector
- selector.Reset();
- selector.mTag = pseudoClassList->mAtom; // steal ref count
+ nsCSSSelector *pseudoElement = new nsCSSSelector;
+ if (!pseudoElement) {
+ aErrorCode = NS_ERROR_OUT_OF_MEMORY;
+ return PR_FALSE;
+ }
+ pseudoElement->mTag = pseudoClassList->mAtom; // steal ref count
#ifdef INCLUDE_XUL
- if (IsTreePseudoElement(selector.mTag)) {
+ if (IsTreePseudoElement(pseudoElement->mTag)) {
// Take the remaining "pseudoclasses" that we parsed
// inside the tree pseudoelement's ()-list, and
// make our new selector have these pseudoclasses
// in its pseudoclass list.
- selector.mPseudoClassList = pseudoClassList->mNext;
+ pseudoElement->mPseudoClassList = pseudoClassList->mNext;
pseudoClassList->mNext = nsnull;
}
#endif
- list->AddSelector(selector);
+ list->AddSelector(pseudoElement);
+
+ // remember, headSelector is the first non-pseudo element
pseudoClassList->mAtom = nsnull;
- listSel->mOperator = PRUnichar('>');
+ headSelector->mOperator = PRUnichar('>');
if (nsnull == prevList) { // delete list entry
- listSel->mPseudoClassList = pseudoClassList->mNext;
+ headSelector->mPseudoClassList = pseudoClassList->mNext;
}
else {
prevList->mNext = pseudoClassList->mNext;
}
pseudoClassList->mNext = nsnull;
delete pseudoClassList;
- weight += listSel->CalcWeight(); // capture weight from remainder
+ weight += headSelector->CalcWeight(); // capture weight from remainder
}
break; // only one pseudo element per selector
}
@@ -1699,7 +1717,7 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
break;
}
else {
- weight += selector.CalcWeight();
+ weight += headSelector->CalcWeight();
}
}
if (!list) {
diff --git a/layout/style/nsCSSParser.cpp b/layout/style/nsCSSParser.cpp
index 4ce1045e890b..95cb6273eaad 100644
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -89,7 +89,7 @@ struct SelectorList {
SelectorList(void);
~SelectorList(void);
- void AddSelector(const nsCSSSelector& aSelector);
+ void AddSelector(nsCSSSelector* aSelector);
#ifdef NS_DEBUG
void Dump(void);
@@ -121,13 +121,13 @@ SelectorList::~SelectorList()
}
}
-void SelectorList::AddSelector(const nsCSSSelector& aSelector)
+// assumes ownership of the selector!
+// Do not add stack-based nsCSSSelector here!
+void SelectorList::AddSelector(nsCSSSelector* aSelector)
{ // prepend to list
- nsCSSSelector* newSel = new nsCSSSelector(aSelector);
- if (nsnull != newSel) {
- newSel->mNext = mSelectors;
- mSelectors = newSel;
- }
+ NS_ASSERTION(aSelector->mNext == nsnull, "are you sure this is a fresh selector?");
+ aSelector->mNext = mSelectors;
+ mSelectors = aSelector;
}
@@ -1619,8 +1619,12 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
PRInt32 weight = 0;
PRBool havePseudoElement = PR_FALSE;
for (;;) {
- nsCSSSelector selector;
- if (! ParseSelector(aErrorCode, selector)) {
+ nsCSSSelector* headSelector = new nsCSSSelector;
+ if (!headSelector) {
+ aErrorCode = NS_ERROR_OUT_OF_MEMORY;
+ return PR_FALSE;
+ }
+ if (! ParseSelector(aErrorCode, *headSelector)) {
break;
}
if (nsnull == list) {
@@ -1630,52 +1634,66 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
return PR_FALSE;
}
}
- list->AddSelector(selector);
- nsCSSSelector* listSel = list->mSelectors;
+
+ list->AddSelector(headSelector);
+
+ // from here on out, we maintain headSelector as the first
+ // non-pseudo element
// pull out pseudo elements here
nsAtomStringList* prevList = nsnull;
- nsAtomStringList* pseudoClassList = listSel->mPseudoClassList;
+ nsAtomStringList* pseudoClassList = headSelector->mPseudoClassList;
while (nsnull != pseudoClassList) {
if (! IsPseudoClass(pseudoClassList->mAtom)) {
havePseudoElement = PR_TRUE;
- if (IsSinglePseudoClass(*listSel)) { // convert to pseudo element selector
+ if (IsSinglePseudoClass(*headSelector)) { // convert to pseudo element selector
nsIAtom* pseudoElement = pseudoClassList->mAtom; // steal ref count
pseudoClassList->mAtom = nsnull;
- listSel->Reset();
- if (listSel->mNext) {// more to the selector
- listSel->mOperator = PRUnichar('>');
- nsCSSSelector empty;
- list->AddSelector(empty); // leave a blank (universal) selector in the middle
- listSel = list->mSelectors; // use the new one for the pseudo
+ headSelector->Reset();
+ if (headSelector->mNext) {// more to the selector
+ headSelector->mOperator = PRUnichar('>');
+ headSelector = new nsCSSSelector;
+ if (!headSelector) {
+ aErrorCode = NS_ERROR_OUT_OF_MEMORY;
+ return PR_FALSE;
+ }
+
+ // leave a blank (universal) selector in the middle
+ list->AddSelector(headSelector);
}
- listSel->mTag = pseudoElement;
+ headSelector->mTag = pseudoElement;
}
else { // append new pseudo element selector
- selector.Reset();
- selector.mTag = pseudoClassList->mAtom; // steal ref count
+ nsCSSSelector *pseudoElement = new nsCSSSelector;
+ if (!pseudoElement) {
+ aErrorCode = NS_ERROR_OUT_OF_MEMORY;
+ return PR_FALSE;
+ }
+ pseudoElement->mTag = pseudoClassList->mAtom; // steal ref count
#ifdef INCLUDE_XUL
- if (IsTreePseudoElement(selector.mTag)) {
+ if (IsTreePseudoElement(pseudoElement->mTag)) {
// Take the remaining "pseudoclasses" that we parsed
// inside the tree pseudoelement's ()-list, and
// make our new selector have these pseudoclasses
// in its pseudoclass list.
- selector.mPseudoClassList = pseudoClassList->mNext;
+ pseudoElement->mPseudoClassList = pseudoClassList->mNext;
pseudoClassList->mNext = nsnull;
}
#endif
- list->AddSelector(selector);
+ list->AddSelector(pseudoElement);
+
+ // remember, headSelector is the first non-pseudo element
pseudoClassList->mAtom = nsnull;
- listSel->mOperator = PRUnichar('>');
+ headSelector->mOperator = PRUnichar('>');
if (nsnull == prevList) { // delete list entry
- listSel->mPseudoClassList = pseudoClassList->mNext;
+ headSelector->mPseudoClassList = pseudoClassList->mNext;
}
else {
prevList->mNext = pseudoClassList->mNext;
}
pseudoClassList->mNext = nsnull;
delete pseudoClassList;
- weight += listSel->CalcWeight(); // capture weight from remainder
+ weight += headSelector->CalcWeight(); // capture weight from remainder
}
break; // only one pseudo element per selector
}
@@ -1699,7 +1717,7 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
break;
}
else {
- weight += selector.CalcWeight();
+ weight += headSelector->CalcWeight();
}
}
if (!list) {