зеркало из https://github.com/mozilla/gecko-dev.git
Stop using potentially-deep recursion to serialize selectors. (Bug 475215) r+sr=bzbarsky
This commit is contained in:
Родитель
b02ed9db5c
Коммит
62f38efea1
|
@ -75,6 +75,7 @@
|
|||
#include "nsIPrincipal.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsCSSPseudoClasses.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsContentErrors.h"
|
||||
|
@ -468,11 +469,6 @@ static PRBool IsPseudoElement(nsIAtom* aAtom)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void nsCSSSelector::AppendNegationToString(nsAString& aString)
|
||||
{
|
||||
aString.AppendLiteral(":not(");
|
||||
}
|
||||
|
||||
//
|
||||
// Builds the textual representation of a selector. Called by DOM 2 CSS
|
||||
// StyleRule:selectorText
|
||||
|
@ -484,28 +480,58 @@ nsCSSSelector::ToString(nsAString& aString, nsICSSStyleSheet* aSheet,
|
|||
if (!aAppend)
|
||||
aString.Truncate();
|
||||
|
||||
ToStringInternal(aString, aSheet, IsPseudoElement(mTag), PR_FALSE);
|
||||
// selectors are linked from right-to-left, so the next selector in
|
||||
// the linked list actually precedes this one in the resulting string
|
||||
nsAutoTArray<const nsCSSSelector*, 8> stack;
|
||||
for (const nsCSSSelector *s = this; s; s = s->mNext) {
|
||||
stack.AppendElement(s);
|
||||
}
|
||||
|
||||
while (!stack.IsEmpty()) {
|
||||
PRUint32 index = stack.Length() - 1;
|
||||
const nsCSSSelector *s = stack.ElementAt(index);
|
||||
stack.RemoveElementAt(index);
|
||||
|
||||
s->AppendToStringWithoutCombinators(aString, aSheet);
|
||||
|
||||
// Append the combinator, if needed.
|
||||
if (!stack.IsEmpty()) {
|
||||
const nsCSSSelector *next = stack.ElementAt(index - 1);
|
||||
if (!IsPseudoElement(next->mTag)) {
|
||||
aString.Append(PRUnichar(' '));
|
||||
PRUnichar oper = s->mOperator;
|
||||
if (oper != PRUnichar(0)) {
|
||||
aString.Append(oper);
|
||||
aString.Append(PRUnichar(' '));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void nsCSSSelector::ToStringInternal(nsAString& aString,
|
||||
nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsPseudoElem,
|
||||
void
|
||||
nsCSSSelector::AppendToStringWithoutCombinators
|
||||
(nsAString& aString, nsICSSStyleSheet* aSheet) const
|
||||
{
|
||||
AppendToStringWithoutCombinatorsOrNegations(aString, aSheet, PR_FALSE);
|
||||
|
||||
for (const nsCSSSelector* negation = mNegations; negation;
|
||||
negation = negation->mNegations) {
|
||||
aString.AppendLiteral(":not(");
|
||||
negation->AppendToStringWithoutCombinatorsOrNegations(aString, aSheet,
|
||||
PR_TRUE);
|
||||
aString.Append(PRUnichar(')'));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations
|
||||
(nsAString& aString, nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsNegated) const
|
||||
{
|
||||
nsAutoString temp;
|
||||
PRBool isPseudoElement = IsPseudoElement(mTag);
|
||||
|
||||
// selectors are linked from right-to-left, so the next selector in the linked list
|
||||
// actually precedes this one in the resulting string
|
||||
if (mNext) {
|
||||
mNext->ToStringInternal(aString, aSheet, IsPseudoElement(mTag), 0);
|
||||
if (!aIsNegated && !isPseudoElement) {
|
||||
// don't add a leading whitespace if we have a pseudo-element
|
||||
// or a negated simple selector
|
||||
aString.Append(PRUnichar(' '));
|
||||
}
|
||||
}
|
||||
|
||||
// For non-pseudo-element selectors or for lone pseudo-elements, deal with
|
||||
// namespace prefixes.
|
||||
PRBool wroteNamespace = PR_FALSE;
|
||||
|
@ -697,22 +723,6 @@ void nsCSSSelector::ToStringInternal(nsAString& aString,
|
|||
list = list->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aIsNegated) {
|
||||
for (nsCSSSelector* negation = mNegations; negation;
|
||||
negation = negation->mNegations) {
|
||||
aString.AppendLiteral(":not(");
|
||||
negation->ToStringInternal(aString, aSheet, PR_FALSE, PR_TRUE);
|
||||
aString.Append(PRUnichar(')'));
|
||||
}
|
||||
}
|
||||
|
||||
// Append the operator only if the selector is not negated and is not
|
||||
// a pseudo-element
|
||||
if (!aIsNegated && mOperator && !aIsPseudoElem) {
|
||||
aString.Append(PRUnichar(' '));
|
||||
aString.Append(mOperator);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
|
|
@ -173,10 +173,12 @@ private:
|
|||
void AddPseudoClassInternal(nsPseudoClassList *aPseudoClass);
|
||||
nsCSSSelector* Clone(PRBool aDeepNext, PRBool aDeepNegations) const;
|
||||
|
||||
void AppendNegationToString(nsAString& aString);
|
||||
void ToStringInternal(nsAString& aString, nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsPseudoElem,
|
||||
PRBool aIsNegated) const;
|
||||
void AppendToStringWithoutCombinators(nsAString& aString,
|
||||
nsICSSStyleSheet* aSheet) const;
|
||||
void AppendToStringWithoutCombinatorsOrNegations(nsAString& aString,
|
||||
nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsNegated)
|
||||
const;
|
||||
// Returns true if this selector can have a namespace specified (which
|
||||
// happens if and only if the default namespace would apply to this
|
||||
// selector).
|
||||
|
|
Загрузка…
Ссылка в новой задаче