prep work for fixing bug 180379 - stop creating extra nsCSSSelectors - instead of creating them on the stack then copying them to the heap, start with them newly on the heap.

r=bzbarsky, sr=dbaron
This commit is contained in:
alecf%netscape.com 2002-11-16 05:37:24 +00:00
Родитель aa24697417
Коммит 3dc37760d5
2 изменённых файлов: 94 добавлений и 58 удалений

Просмотреть файл

@ -89,7 +89,7 @@ struct SelectorList {
SelectorList(void); SelectorList(void);
~SelectorList(void); ~SelectorList(void);
void AddSelector(const nsCSSSelector& aSelector); void AddSelector(nsCSSSelector* aSelector);
#ifdef NS_DEBUG #ifdef NS_DEBUG
void Dump(void); 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 { // prepend to list
nsCSSSelector* newSel = new nsCSSSelector(aSelector); NS_ASSERTION(aSelector->mNext == nsnull, "are you sure this is a fresh selector?");
if (nsnull != newSel) { aSelector->mNext = mSelectors;
newSel->mNext = mSelectors; mSelectors = aSelector;
mSelectors = newSel;
}
} }
@ -1619,8 +1619,12 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
PRInt32 weight = 0; PRInt32 weight = 0;
PRBool havePseudoElement = PR_FALSE; PRBool havePseudoElement = PR_FALSE;
for (;;) { for (;;) {
nsCSSSelector selector; nsCSSSelector* headSelector = new nsCSSSelector;
if (! ParseSelector(aErrorCode, selector)) { if (!headSelector) {
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
return PR_FALSE;
}
if (! ParseSelector(aErrorCode, *headSelector)) {
break; break;
} }
if (nsnull == list) { if (nsnull == list) {
@ -1630,52 +1634,66 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
return PR_FALSE; 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 // pull out pseudo elements here
nsAtomStringList* prevList = nsnull; nsAtomStringList* prevList = nsnull;
nsAtomStringList* pseudoClassList = listSel->mPseudoClassList; nsAtomStringList* pseudoClassList = headSelector->mPseudoClassList;
while (nsnull != pseudoClassList) { while (nsnull != pseudoClassList) {
if (! IsPseudoClass(pseudoClassList->mAtom)) { if (! IsPseudoClass(pseudoClassList->mAtom)) {
havePseudoElement = PR_TRUE; 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 nsIAtom* pseudoElement = pseudoClassList->mAtom; // steal ref count
pseudoClassList->mAtom = nsnull; pseudoClassList->mAtom = nsnull;
listSel->Reset(); headSelector->Reset();
if (listSel->mNext) {// more to the selector if (headSelector->mNext) {// more to the selector
listSel->mOperator = PRUnichar('>'); headSelector->mOperator = PRUnichar('>');
nsCSSSelector empty; headSelector = new nsCSSSelector;
list->AddSelector(empty); // leave a blank (universal) selector in the middle if (!headSelector) {
listSel = list->mSelectors; // use the new one for the pseudo 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 else { // append new pseudo element selector
selector.Reset(); nsCSSSelector *pseudoElement = new nsCSSSelector;
selector.mTag = pseudoClassList->mAtom; // steal ref count if (!pseudoElement) {
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
return PR_FALSE;
}
pseudoElement->mTag = pseudoClassList->mAtom; // steal ref count
#ifdef INCLUDE_XUL #ifdef INCLUDE_XUL
if (IsTreePseudoElement(selector.mTag)) { if (IsTreePseudoElement(pseudoElement->mTag)) {
// Take the remaining "pseudoclasses" that we parsed // Take the remaining "pseudoclasses" that we parsed
// inside the tree pseudoelement's ()-list, and // inside the tree pseudoelement's ()-list, and
// make our new selector have these pseudoclasses // make our new selector have these pseudoclasses
// in its pseudoclass list. // in its pseudoclass list.
selector.mPseudoClassList = pseudoClassList->mNext; pseudoElement->mPseudoClassList = pseudoClassList->mNext;
pseudoClassList->mNext = nsnull; pseudoClassList->mNext = nsnull;
} }
#endif #endif
list->AddSelector(selector); list->AddSelector(pseudoElement);
// remember, headSelector is the first non-pseudo element
pseudoClassList->mAtom = nsnull; pseudoClassList->mAtom = nsnull;
listSel->mOperator = PRUnichar('>'); headSelector->mOperator = PRUnichar('>');
if (nsnull == prevList) { // delete list entry if (nsnull == prevList) { // delete list entry
listSel->mPseudoClassList = pseudoClassList->mNext; headSelector->mPseudoClassList = pseudoClassList->mNext;
} }
else { else {
prevList->mNext = pseudoClassList->mNext; prevList->mNext = pseudoClassList->mNext;
} }
pseudoClassList->mNext = nsnull; pseudoClassList->mNext = nsnull;
delete pseudoClassList; delete pseudoClassList;
weight += listSel->CalcWeight(); // capture weight from remainder weight += headSelector->CalcWeight(); // capture weight from remainder
} }
break; // only one pseudo element per selector break; // only one pseudo element per selector
} }
@ -1699,7 +1717,7 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
break; break;
} }
else { else {
weight += selector.CalcWeight(); weight += headSelector->CalcWeight();
} }
} }
if (!list) { if (!list) {

Просмотреть файл

@ -89,7 +89,7 @@ struct SelectorList {
SelectorList(void); SelectorList(void);
~SelectorList(void); ~SelectorList(void);
void AddSelector(const nsCSSSelector& aSelector); void AddSelector(nsCSSSelector* aSelector);
#ifdef NS_DEBUG #ifdef NS_DEBUG
void Dump(void); 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 { // prepend to list
nsCSSSelector* newSel = new nsCSSSelector(aSelector); NS_ASSERTION(aSelector->mNext == nsnull, "are you sure this is a fresh selector?");
if (nsnull != newSel) { aSelector->mNext = mSelectors;
newSel->mNext = mSelectors; mSelectors = aSelector;
mSelectors = newSel;
}
} }
@ -1619,8 +1619,12 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
PRInt32 weight = 0; PRInt32 weight = 0;
PRBool havePseudoElement = PR_FALSE; PRBool havePseudoElement = PR_FALSE;
for (;;) { for (;;) {
nsCSSSelector selector; nsCSSSelector* headSelector = new nsCSSSelector;
if (! ParseSelector(aErrorCode, selector)) { if (!headSelector) {
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
return PR_FALSE;
}
if (! ParseSelector(aErrorCode, *headSelector)) {
break; break;
} }
if (nsnull == list) { if (nsnull == list) {
@ -1630,52 +1634,66 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
return PR_FALSE; 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 // pull out pseudo elements here
nsAtomStringList* prevList = nsnull; nsAtomStringList* prevList = nsnull;
nsAtomStringList* pseudoClassList = listSel->mPseudoClassList; nsAtomStringList* pseudoClassList = headSelector->mPseudoClassList;
while (nsnull != pseudoClassList) { while (nsnull != pseudoClassList) {
if (! IsPseudoClass(pseudoClassList->mAtom)) { if (! IsPseudoClass(pseudoClassList->mAtom)) {
havePseudoElement = PR_TRUE; 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 nsIAtom* pseudoElement = pseudoClassList->mAtom; // steal ref count
pseudoClassList->mAtom = nsnull; pseudoClassList->mAtom = nsnull;
listSel->Reset(); headSelector->Reset();
if (listSel->mNext) {// more to the selector if (headSelector->mNext) {// more to the selector
listSel->mOperator = PRUnichar('>'); headSelector->mOperator = PRUnichar('>');
nsCSSSelector empty; headSelector = new nsCSSSelector;
list->AddSelector(empty); // leave a blank (universal) selector in the middle if (!headSelector) {
listSel = list->mSelectors; // use the new one for the pseudo 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 else { // append new pseudo element selector
selector.Reset(); nsCSSSelector *pseudoElement = new nsCSSSelector;
selector.mTag = pseudoClassList->mAtom; // steal ref count if (!pseudoElement) {
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
return PR_FALSE;
}
pseudoElement->mTag = pseudoClassList->mAtom; // steal ref count
#ifdef INCLUDE_XUL #ifdef INCLUDE_XUL
if (IsTreePseudoElement(selector.mTag)) { if (IsTreePseudoElement(pseudoElement->mTag)) {
// Take the remaining "pseudoclasses" that we parsed // Take the remaining "pseudoclasses" that we parsed
// inside the tree pseudoelement's ()-list, and // inside the tree pseudoelement's ()-list, and
// make our new selector have these pseudoclasses // make our new selector have these pseudoclasses
// in its pseudoclass list. // in its pseudoclass list.
selector.mPseudoClassList = pseudoClassList->mNext; pseudoElement->mPseudoClassList = pseudoClassList->mNext;
pseudoClassList->mNext = nsnull; pseudoClassList->mNext = nsnull;
} }
#endif #endif
list->AddSelector(selector); list->AddSelector(pseudoElement);
// remember, headSelector is the first non-pseudo element
pseudoClassList->mAtom = nsnull; pseudoClassList->mAtom = nsnull;
listSel->mOperator = PRUnichar('>'); headSelector->mOperator = PRUnichar('>');
if (nsnull == prevList) { // delete list entry if (nsnull == prevList) { // delete list entry
listSel->mPseudoClassList = pseudoClassList->mNext; headSelector->mPseudoClassList = pseudoClassList->mNext;
} }
else { else {
prevList->mNext = pseudoClassList->mNext; prevList->mNext = pseudoClassList->mNext;
} }
pseudoClassList->mNext = nsnull; pseudoClassList->mNext = nsnull;
delete pseudoClassList; delete pseudoClassList;
weight += listSel->CalcWeight(); // capture weight from remainder weight += headSelector->CalcWeight(); // capture weight from remainder
} }
break; // only one pseudo element per selector break; // only one pseudo element per selector
} }
@ -1699,7 +1717,7 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
break; break;
} }
else { else {
weight += selector.CalcWeight(); weight += headSelector->CalcWeight();
} }
} }
if (!list) { if (!list) {