зеркало из https://github.com/mozilla/pjs.git
Create only one CSSStyleRuleImpl per rule rather than one per comma-separated selector to fix CSSOM compliance bugs and make rule immutability easier. Store list of selectors on the CSSStyleRuleImpl, each with their own weight. b=98765 r+sr=bzbarsky
This commit is contained in:
Родитель
c3600c1ce8
Коммит
47ed1de93c
|
@ -87,62 +87,6 @@
|
|||
|
||||
//#define ENABLE_COUNTERS // un-comment this to enable counters (bug 15174)
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(SelectorList)
|
||||
|
||||
// e.g. "P B, H1 B { ... }" has a selector list with two elements,
|
||||
// each of which has two selectors.
|
||||
struct SelectorList {
|
||||
SelectorList(void);
|
||||
~SelectorList(void);
|
||||
|
||||
void AddSelector(const nsCSSSelector& aSelector);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
void Dump(void);
|
||||
#endif
|
||||
|
||||
nsCSSSelector* mSelectors;
|
||||
PRInt32 mWeight;
|
||||
SelectorList* mNext;
|
||||
};
|
||||
|
||||
SelectorList::SelectorList(void)
|
||||
: mSelectors(nsnull),
|
||||
mNext(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(SelectorList);
|
||||
}
|
||||
|
||||
SelectorList::~SelectorList()
|
||||
{
|
||||
MOZ_COUNT_DTOR(SelectorList);
|
||||
nsCSSSelector* sel = mSelectors;
|
||||
while (nsnull != sel) {
|
||||
nsCSSSelector* dead = sel;
|
||||
sel = sel->mNext;
|
||||
delete dead;
|
||||
}
|
||||
if (nsnull != mNext) {
|
||||
delete mNext;
|
||||
}
|
||||
}
|
||||
|
||||
void SelectorList::AddSelector(const nsCSSSelector& aSelector)
|
||||
{ // prepend to list
|
||||
nsCSSSelector* newSel = new nsCSSSelector(aSelector);
|
||||
if (nsnull != newSel) {
|
||||
newSel->mNext = mSelectors;
|
||||
mSelectors = newSel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
void SelectorList::Dump()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Your basic top-down recursive descent style parser
|
||||
|
@ -240,8 +184,8 @@ protected:
|
|||
void ParseLangSelector(nsCSSSelector& aSelector, PRInt32& aParsingStatus,
|
||||
PRInt32& aErrorCode);
|
||||
|
||||
PRBool ParseSelectorList(PRInt32& aErrorCode, SelectorList*& aListHead);
|
||||
PRBool ParseSelectorGroup(PRInt32& aErrorCode, SelectorList*& aListHead);
|
||||
PRBool ParseSelectorList(PRInt32& aErrorCode, nsCSSSelectorList*& aListHead);
|
||||
PRBool ParseSelectorGroup(PRInt32& aErrorCode, nsCSSSelectorList*& aListHead);
|
||||
PRBool ParseSelector(PRInt32& aErrorCode, nsCSSSelector& aSelectorResult);
|
||||
nsCSSDeclaration* ParseDeclarationBlock(PRInt32& aErrorCode,
|
||||
PRBool aCheckForBraces);
|
||||
|
@ -692,12 +636,15 @@ CSSParserImpl::ParseStyleAttribute(const nsAString& aAttributeValue,
|
|||
haveBraces = PR_FALSE;
|
||||
}
|
||||
|
||||
nsCSSDeclaration* declaration =
|
||||
ParseDeclarationBlock(errorCode, haveBraces);
|
||||
if (nsnull != declaration) {
|
||||
nsCSSDeclaration* declaration = ParseDeclarationBlock(errorCode, haveBraces);
|
||||
if (declaration) {
|
||||
// Create a style rule for the delcaration
|
||||
nsICSSStyleRule* rule = nsnull;
|
||||
NS_NewCSSStyleRule(&rule, nsCSSSelector());
|
||||
rv = NS_NewCSSStyleRule(&rule, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
declaration->RuleAbort();
|
||||
return rv;
|
||||
}
|
||||
rule->SetDeclaration(declaration);
|
||||
*aResult = rule;
|
||||
}
|
||||
|
@ -1496,7 +1443,7 @@ void CSSParserImpl::AppendRule(nsICSSRule* aRule)
|
|||
PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode, RuleAppendFunc aAppendFunc, void* aData)
|
||||
{
|
||||
// First get the list of selectors for the rule
|
||||
SelectorList* slist = nsnull;
|
||||
nsCSSSelectorList* slist = nsnull;
|
||||
PRUint32 linenum = mScanner->GetLineNumber();
|
||||
if (! ParseSelectorList(aErrorCode, slist)) {
|
||||
REPORT_UNEXPECTED(
|
||||
|
@ -1525,38 +1472,24 @@ PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode, RuleAppendFunc aAppendFu
|
|||
|
||||
// Translate the selector list and declaration block into style data
|
||||
|
||||
SelectorList* list = slist;
|
||||
|
||||
while (nsnull != list) {
|
||||
nsICSSStyleRule* rule = nsnull;
|
||||
|
||||
NS_NewCSSStyleRule(&rule, *(list->mSelectors));
|
||||
if (nsnull != rule) {
|
||||
if (nsnull != list->mSelectors->mNext) { // hand off other selectors to new rule
|
||||
nsCSSSelector* ruleFirst = rule->FirstSelector();
|
||||
ruleFirst->mNext = list->mSelectors->mNext;
|
||||
list->mSelectors->mNext = nsnull;
|
||||
}
|
||||
rule->SetLineNumber(linenum);
|
||||
rule->SetDeclaration(declaration);
|
||||
rule->SetWeight(list->mWeight);
|
||||
// rule->List();
|
||||
(*aAppendFunc)(rule, aData);
|
||||
NS_RELEASE(rule);
|
||||
}
|
||||
|
||||
list = list->mNext;
|
||||
nsCOMPtr<nsICSSStyleRule> rule;
|
||||
NS_NewCSSStyleRule(getter_AddRefs(rule), slist);
|
||||
if (!rule) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
delete slist;
|
||||
return PR_FALSE;
|
||||
}
|
||||
rule->SetLineNumber(linenum);
|
||||
rule->SetDeclaration(declaration);
|
||||
(*aAppendFunc)(rule, aData);
|
||||
|
||||
// Release temporary storage
|
||||
delete slist;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
|
||||
SelectorList*& aListHead)
|
||||
nsCSSSelectorList*& aListHead)
|
||||
{
|
||||
SelectorList* list = nsnull;
|
||||
nsCSSSelectorList* list = nsnull;
|
||||
if (! ParseSelectorGroup(aErrorCode, list)) {
|
||||
// must have at least one selector group
|
||||
aListHead = nsnull;
|
||||
|
@ -1575,7 +1508,7 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
|
|||
|
||||
if (eCSSToken_Symbol == tk->mType) {
|
||||
if (',' == tk->mSymbol) {
|
||||
SelectorList* newList = nsnull;
|
||||
nsCSSSelectorList* newList = nsnull;
|
||||
// Another selector group must follow
|
||||
if (! ParseSelectorGroup(aErrorCode, newList)) {
|
||||
break;
|
||||
|
@ -1627,9 +1560,9 @@ static PRBool IsTreePseudoElement(nsIAtom* aPseudo)
|
|||
#endif
|
||||
|
||||
PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
|
||||
SelectorList*& aList)
|
||||
nsCSSSelectorList*& aList)
|
||||
{
|
||||
SelectorList* list = nsnull;
|
||||
nsCSSSelectorList* list = nsnull;
|
||||
PRUnichar combinator = PRUnichar(0);
|
||||
PRInt32 weight = 0;
|
||||
PRBool havePseudoElement = PR_FALSE;
|
||||
|
@ -1639,7 +1572,7 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
|
|||
break;
|
||||
}
|
||||
if (nsnull == list) {
|
||||
list = new SelectorList();
|
||||
list = new nsCSSSelectorList();
|
||||
if (nsnull == list) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
return PR_FALSE;
|
||||
|
|
|
@ -537,8 +537,16 @@ void nsCSSSelector::AppendNegationToString(nsAString& aString)
|
|||
// Builds the textual representation of a selector. Called by DOM 2 CSS
|
||||
// StyleRule:selectorText
|
||||
//
|
||||
nsresult nsCSSSelector::ToString( nsAString& aString, nsICSSStyleSheet* aSheet, PRBool aIsPseudoElem,
|
||||
PRInt8 aNegatedIndex) const
|
||||
void
|
||||
nsCSSSelector::ToString(nsAString& aString, nsICSSStyleSheet* aSheet) const
|
||||
{
|
||||
ToStringInternal(aString, aSheet, IsPseudoElement(mTag), 0);
|
||||
}
|
||||
|
||||
void nsCSSSelector::ToStringInternal(nsAString& aString,
|
||||
nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsPseudoElem,
|
||||
PRIntn aNegatedIndex) const
|
||||
{
|
||||
nsAutoString temp;
|
||||
PRBool aIsNegated = PRBool(0 < aNegatedIndex);
|
||||
|
@ -546,7 +554,7 @@ nsresult nsCSSSelector::ToString( nsAString& aString, nsICSSStyleSheet* aSheet,
|
|||
// 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->ToString(aString, aSheet, IsPseudoElement(mTag), PR_FALSE);
|
||||
mNext->ToStringInternal(aString, aSheet, IsPseudoElement(mTag), 0);
|
||||
if (!aIsNegated && !IsPseudoElement(mTag)) {
|
||||
// don't add a leading whitespace if we have a pseudo-element
|
||||
// or a negated simple selector
|
||||
|
@ -685,7 +693,7 @@ nsresult nsCSSSelector::ToString( nsAString& aString, nsICSSStyleSheet* aSheet,
|
|||
|
||||
if (mNegations) {
|
||||
// chain all the negated selectors
|
||||
mNegations->ToString(aString, aSheet, PR_FALSE, aNegatedIndex + 1);
|
||||
mNegations->ToStringInternal(aString, aSheet, PR_FALSE, aNegatedIndex + 1);
|
||||
}
|
||||
|
||||
// Append the operator only if the selector is not negated and is not
|
||||
|
@ -694,9 +702,82 @@ nsresult nsCSSSelector::ToString( nsAString& aString, nsICSSStyleSheet* aSheet,
|
|||
aString.Append(PRUnichar(' '));
|
||||
aString.Append(mOperator);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// -- nsCSSSelectorList -------------------------------
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsCSSSelectorList)
|
||||
|
||||
nsCSSSelectorList::nsCSSSelectorList(void)
|
||||
: mSelectors(nsnull),
|
||||
mNext(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsCSSSelectorList);
|
||||
}
|
||||
|
||||
nsCSSSelectorList::~nsCSSSelectorList()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsCSSSelectorList);
|
||||
nsCSSSelector* sel = mSelectors;
|
||||
while (sel) {
|
||||
nsCSSSelector* dead = sel;
|
||||
sel = sel->mNext;
|
||||
delete dead;
|
||||
}
|
||||
if (mNext) {
|
||||
delete mNext;
|
||||
}
|
||||
}
|
||||
|
||||
void nsCSSSelectorList::AddSelector(const nsCSSSelector& aSelector)
|
||||
{ // prepend to list
|
||||
nsCSSSelector* newSel = new nsCSSSelector(aSelector);
|
||||
if (newSel) {
|
||||
newSel->mNext = mSelectors;
|
||||
mSelectors = newSel;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSSelectorList::ToString(nsAString& aResult, nsICSSStyleSheet* aSheet)
|
||||
{
|
||||
nsCSSSelectorList *p = this;
|
||||
for (;;) {
|
||||
p->mSelectors->ToString(aResult, aSheet);
|
||||
p = p->mNext;
|
||||
if (!p)
|
||||
break;
|
||||
aResult.Append(NS_LITERAL_STRING(", "));
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSSelectorList*
|
||||
nsCSSSelectorList::Clone()
|
||||
{
|
||||
nsCSSSelectorList *list = nsnull;
|
||||
nsCSSSelectorList **list_cur = &list;
|
||||
for (nsCSSSelectorList *l = this; l; l = l->mNext) {
|
||||
nsCSSSelectorList *lcopy = new nsCSSSelectorList();
|
||||
if (!lcopy) {
|
||||
delete list;
|
||||
return nsnull;
|
||||
}
|
||||
*list_cur = lcopy;
|
||||
list_cur = &lcopy->mNext;
|
||||
|
||||
nsCSSSelector **sel_cur = &lcopy->mSelectors;
|
||||
for (nsCSSSelector *s = l->mSelectors; s; s = s->mNext) {
|
||||
nsCSSSelector *scopy = new nsCSSSelector(*s);
|
||||
if (!scopy) {
|
||||
delete list;
|
||||
return nsnull;
|
||||
}
|
||||
*sel_cur = scopy;
|
||||
sel_cur = &scopy->mNext;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// -- CSSImportantRule -------------------------------
|
||||
|
||||
|
@ -1046,16 +1127,12 @@ class CSSStyleRuleImpl : public nsCSSRule,
|
|||
public nsIDOMCSSStyleRule
|
||||
{
|
||||
public:
|
||||
CSSStyleRuleImpl(const nsCSSSelector& aSelector);
|
||||
CSSStyleRuleImpl(nsCSSSelectorList* aSelector);
|
||||
CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
virtual nsCSSSelector* FirstSelector(void);
|
||||
virtual void AddSelector(const nsCSSSelector& aSelector);
|
||||
virtual void DeleteSelector(nsCSSSelector* aSelector);
|
||||
virtual void SetSourceSelectorText(const nsString& aSelectorText);
|
||||
virtual void GetSourceSelectorText(nsString& aSelectorText) const;
|
||||
virtual nsCSSSelectorList* Selector(void);
|
||||
|
||||
virtual PRUint32 GetLineNumber(void) const;
|
||||
virtual void SetLineNumber(PRUint32 aLineNumber);
|
||||
|
@ -1063,9 +1140,6 @@ public:
|
|||
virtual nsCSSDeclaration* GetDeclaration(void) const;
|
||||
virtual void SetDeclaration(nsCSSDeclaration* aDeclaration);
|
||||
|
||||
virtual PRInt32 GetWeight(void) const;
|
||||
virtual void SetWeight(PRInt32 aWeight);
|
||||
|
||||
virtual already_AddRefed<nsIStyleRule> GetImportantRule(void);
|
||||
|
||||
// hook for inspector
|
||||
|
@ -1100,39 +1174,28 @@ protected:
|
|||
virtual ~CSSStyleRuleImpl(void);
|
||||
|
||||
protected:
|
||||
nsCSSSelector mSelector;
|
||||
nsCSSDeclaration* mDeclaration;
|
||||
PRInt32 mWeight;
|
||||
nsCSSSelectorList* mSelector; // null for style attribute
|
||||
nsCSSDeclaration* mDeclaration;
|
||||
CSSImportantRule* mImportantRule;
|
||||
DOMCSSDeclarationImpl* mDOMDeclaration;
|
||||
PRUint32 mLineNumber;
|
||||
};
|
||||
|
||||
CSSStyleRuleImpl::CSSStyleRuleImpl(const nsCSSSelector& aSelector)
|
||||
CSSStyleRuleImpl::CSSStyleRuleImpl(nsCSSSelectorList* aSelector)
|
||||
: nsCSSRule(),
|
||||
mSelector(aSelector), mDeclaration(nsnull),
|
||||
mWeight(0), mImportantRule(nsnull),
|
||||
mImportantRule(nsnull),
|
||||
mDOMDeclaration(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
CSSStyleRuleImpl::CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy)
|
||||
: nsCSSRule(aCopy),
|
||||
mSelector(aCopy.mSelector),
|
||||
mSelector(aCopy.mSelector ? aCopy.mSelector->Clone() : nsnull),
|
||||
mDeclaration(nsnull),
|
||||
mWeight(aCopy.mWeight),
|
||||
mImportantRule(nsnull),
|
||||
mDOMDeclaration(nsnull)
|
||||
{
|
||||
nsCSSSelector* copySel = aCopy.mSelector.mNext;
|
||||
nsCSSSelector* ourSel = &mSelector;
|
||||
|
||||
while (copySel && ourSel) {
|
||||
ourSel->mNext = new nsCSSSelector(*copySel);
|
||||
ourSel = ourSel->mNext;
|
||||
copySel = copySel->mNext;
|
||||
}
|
||||
|
||||
if (aCopy.mDeclaration) {
|
||||
mDeclaration = aCopy.mDeclaration->Clone();
|
||||
if (nsnull != mDeclaration) {
|
||||
|
@ -1145,12 +1208,9 @@ CSSStyleRuleImpl::CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy)
|
|||
|
||||
CSSStyleRuleImpl::~CSSStyleRuleImpl(void)
|
||||
{
|
||||
nsCSSSelector* next = mSelector.mNext;
|
||||
|
||||
while (nsnull != next) {
|
||||
nsCSSSelector* selector = next;
|
||||
next = selector->mNext;
|
||||
delete selector;
|
||||
if (mSelector) {
|
||||
delete mSelector;
|
||||
mSelector = nsnull;
|
||||
}
|
||||
if (nsnull != mDeclaration) {
|
||||
mDeclaration->Release();
|
||||
|
@ -1182,61 +1242,9 @@ NS_IMPL_ADDREF_INHERITED(CSSStyleRuleImpl, nsCSSRule);
|
|||
NS_IMPL_RELEASE_INHERITED(CSSStyleRuleImpl, nsCSSRule);
|
||||
|
||||
|
||||
nsCSSSelector* CSSStyleRuleImpl::FirstSelector(void)
|
||||
nsCSSSelectorList* CSSStyleRuleImpl::Selector(void)
|
||||
{
|
||||
return &mSelector;
|
||||
}
|
||||
|
||||
void CSSStyleRuleImpl::AddSelector(const nsCSSSelector& aSelector)
|
||||
{
|
||||
nsCSSSelector* selector = new nsCSSSelector(aSelector);
|
||||
nsCSSSelector* last = &mSelector;
|
||||
|
||||
while (nsnull != last->mNext) {
|
||||
last = last->mNext;
|
||||
}
|
||||
last->mNext = selector;
|
||||
}
|
||||
|
||||
|
||||
void CSSStyleRuleImpl::DeleteSelector(nsCSSSelector* aSelector)
|
||||
{
|
||||
if (nsnull != aSelector) {
|
||||
if (&mSelector == aSelector) { // handle first selector
|
||||
if (nsnull != mSelector.mNext) {
|
||||
nsCSSSelector* nextOne = mSelector.mNext;
|
||||
mSelector = *nextOne; // assign values
|
||||
mSelector.mNext = nextOne->mNext;
|
||||
delete nextOne;
|
||||
}
|
||||
else {
|
||||
mSelector.Reset();
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsCSSSelector* selector = &mSelector;
|
||||
|
||||
while (nsnull != selector->mNext) {
|
||||
if (aSelector == selector->mNext) {
|
||||
selector->mNext = aSelector->mNext;
|
||||
delete aSelector;
|
||||
return;
|
||||
}
|
||||
selector = selector->mNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSSStyleRuleImpl::SetSourceSelectorText(const nsString& aSelectorText)
|
||||
{
|
||||
/* no need for set, since get recreates the string */
|
||||
}
|
||||
|
||||
void CSSStyleRuleImpl::GetSourceSelectorText(nsString& aSelectorText) const
|
||||
{
|
||||
mSelector.ToString( aSelectorText, mSheet, IsPseudoElement(mSelector.mTag),
|
||||
0 );
|
||||
return mSelector;
|
||||
}
|
||||
|
||||
PRUint32 CSSStyleRuleImpl::GetLineNumber(void) const
|
||||
|
@ -1267,16 +1275,6 @@ void CSSStyleRuleImpl::SetDeclaration(nsCSSDeclaration* aDeclaration)
|
|||
}
|
||||
}
|
||||
|
||||
PRInt32 CSSStyleRuleImpl::GetWeight(void) const
|
||||
{
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
void CSSStyleRuleImpl::SetWeight(PRInt32 aWeight)
|
||||
{
|
||||
mWeight = aWeight;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIStyleRule> CSSStyleRuleImpl::GetImportantRule(void)
|
||||
{
|
||||
if (!mImportantRule && mDeclaration) {
|
||||
|
@ -1349,10 +1347,9 @@ CSSStyleRuleImpl::List(FILE* out, PRInt32 aIndent) const
|
|||
for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
|
||||
|
||||
nsAutoString buffer;
|
||||
mSelector.ToString(buffer, mSheet, PR_FALSE, 0);
|
||||
if (mSelector)
|
||||
mSelector->ToString(buffer, mSheet);
|
||||
|
||||
buffer.Append(NS_LITERAL_STRING(" weight: "));
|
||||
buffer.AppendInt(mWeight, 10);
|
||||
buffer.Append(NS_LITERAL_STRING(" "));
|
||||
fputs(NS_LossyConvertUCS2toASCII(buffer).get(), out);
|
||||
if (nsnull != mDeclaration) {
|
||||
|
@ -1378,9 +1375,10 @@ CSSStyleRuleImpl::GetType(PRUint16* aType)
|
|||
NS_IMETHODIMP
|
||||
CSSStyleRuleImpl::GetCssText(nsAString& aCssText)
|
||||
{
|
||||
mSelector.ToString( aCssText, mSheet, IsPseudoElement(mSelector.mTag),
|
||||
0 );
|
||||
aCssText.Append(PRUnichar(' '));
|
||||
if (mSelector) {
|
||||
mSelector->ToString(aCssText, mSheet);
|
||||
aCssText.Append(PRUnichar(' '));
|
||||
}
|
||||
aCssText.Append(PRUnichar('{'));
|
||||
aCssText.Append(PRUnichar(' '));
|
||||
if (mDeclaration)
|
||||
|
@ -1424,7 +1422,10 @@ CSSStyleRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|||
NS_IMETHODIMP
|
||||
CSSStyleRuleImpl::GetSelectorText(nsAString& aSelectorText)
|
||||
{
|
||||
mSelector.ToString( aSelectorText, mSheet, IsPseudoElement(mSelector.mTag), 0 );
|
||||
if (mSelector)
|
||||
mSelector->ToString(aSelectorText, mSheet);
|
||||
else
|
||||
aSelectorText.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1456,7 +1457,7 @@ CSSStyleRuleImpl::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
|||
|
||||
nsresult
|
||||
NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult,
|
||||
const nsCSSSelector& aSelector)
|
||||
nsCSSSelectorList* aSelector)
|
||||
{
|
||||
if (aInstancePtrResult == nsnull) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
|
|
@ -105,9 +105,22 @@
|
|||
#include "nsIScriptSecurityManager.h"
|
||||
|
||||
struct RuleValue {
|
||||
RuleValue(nsICSSStyleRule* aRule, PRInt32 aIndex, RuleValue *aNext)
|
||||
: mRule(aRule), mIndex(aIndex), mNext(aNext) {}
|
||||
/**
|
||||
* |RuleValue|s are constructed before they become part of the
|
||||
* |RuleHash|, to act as rule/selector pairs. |Add| is called when
|
||||
* they are added to the |RuleHash|, and can be considered the second
|
||||
* half of the constructor.
|
||||
*/
|
||||
RuleValue(nsICSSStyleRule* aRule, nsCSSSelector* aSelector)
|
||||
: mRule(aRule), mSelector(aSelector) {}
|
||||
|
||||
RuleValue* Add(PRInt32 aIndex, RuleValue *aNext)
|
||||
{
|
||||
mIndex = aIndex;
|
||||
mNext = aNext;
|
||||
return this;
|
||||
}
|
||||
|
||||
// CAUTION: ~RuleValue will never get called as RuleValues are arena
|
||||
// allocated and arena cleanup will take care of deleting memory.
|
||||
// Add code to RuleHash::~RuleHash to get it to call the destructor
|
||||
|
@ -125,6 +138,7 @@ struct RuleValue {
|
|||
}
|
||||
|
||||
nsICSSStyleRule* mRule;
|
||||
nsCSSSelector* mSelector; // which of |mRule|'s selectors
|
||||
PRInt32 mIndex; // High index means low weight/order.
|
||||
RuleValue* mNext;
|
||||
};
|
||||
|
@ -189,28 +203,28 @@ PR_STATIC_CALLBACK(const void*)
|
|||
RuleHash_TagTable_GetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
||||
{
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*, hdr);
|
||||
return entry->mRules->mRule->FirstSelector()->mTag;
|
||||
return entry->mRules->mSelector->mTag;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(const void*)
|
||||
RuleHash_ClassTable_GetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
||||
{
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*, hdr);
|
||||
return entry->mRules->mRule->FirstSelector()->mClassList->mAtom;
|
||||
return entry->mRules->mSelector->mClassList->mAtom;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(const void*)
|
||||
RuleHash_IdTable_GetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
||||
{
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*, hdr);
|
||||
return entry->mRules->mRule->FirstSelector()->mIDList->mAtom;
|
||||
return entry->mRules->mSelector->mIDList->mAtom;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(const void*)
|
||||
RuleHash_NameSpaceTable_GetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
||||
{
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*, hdr);
|
||||
return NS_INT32_TO_PTR(entry->mRules->mRule->FirstSelector()->mNameSpace);
|
||||
return NS_INT32_TO_PTR(entry->mRules->mSelector->mNameSpace);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashNumber)
|
||||
|
@ -228,7 +242,7 @@ RuleHash_NameSpaceTable_MatchEntry(PLDHashTable *table,
|
|||
NS_STATIC_CAST(const RuleHashTableEntry*, hdr);
|
||||
|
||||
return NS_PTR_TO_INT32(key) ==
|
||||
entry->mRules->mRule->FirstSelector()->mNameSpace;
|
||||
entry->mRules->mSelector->mNameSpace;
|
||||
}
|
||||
|
||||
static PLDHashTableOps RuleHash_TagTable_Ops = {
|
||||
|
@ -322,23 +336,26 @@ static PLDHashTableOps RuleHash_NameSpaceTable_Ops = {
|
|||
#endif
|
||||
|
||||
// Enumerator callback function.
|
||||
typedef void (*RuleEnumFunc)(nsICSSStyleRule* aRule, void *aData);
|
||||
typedef void (*RuleEnumFunc)(nsICSSStyleRule* aRule,
|
||||
nsCSSSelector* aSelector,
|
||||
void *aData);
|
||||
|
||||
class RuleHash {
|
||||
public:
|
||||
RuleHash(PRBool aQuirksMode);
|
||||
~RuleHash();
|
||||
void PrependRule(nsICSSStyleRule* aRule);
|
||||
void PrependRule(RuleValue *aRuleInfo);
|
||||
void EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID,
|
||||
const nsVoidArray& aClassList,
|
||||
RuleEnumFunc aFunc, void* aData);
|
||||
void EnumerateTagRules(nsIAtom* aTag,
|
||||
RuleEnumFunc aFunc, void* aData);
|
||||
PLArenaPool& Arena() { return mArena; }
|
||||
|
||||
protected:
|
||||
void PrependRuleToTable(PLDHashTable* aTable, const void* aKey,
|
||||
nsICSSStyleRule* aRule);
|
||||
void PrependUniversalRule(nsICSSStyleRule* aRule);
|
||||
RuleValue* aRuleInfo);
|
||||
void PrependUniversalRule(RuleValue* aRuleInfo);
|
||||
|
||||
// All rule values in these hashtables are arena allocated
|
||||
PRInt32 mRuleCount;
|
||||
|
@ -436,7 +453,11 @@ RuleHash::~RuleHash(void)
|
|||
do {
|
||||
nsAutoString selectorText;
|
||||
PRUint32 lineNumber = value->mRule->GetLineNumber();
|
||||
value->mRule->GetSourceSelectorText(selectorText);
|
||||
nsCOMPtr<nsIStyleSheet> sheet;
|
||||
value->mRule->GetStyleSheet(*getter_AddRefs(sheet));
|
||||
nsCOMPtr<nsICSSStyleSheet> cssSheet = do_QueryInterface(sheet);
|
||||
value->mSelector->ToString(selectorText, cssSheet);
|
||||
|
||||
printf(" line %d, %s\n",
|
||||
lineNumber, NS_ConvertUCS2toUTF8(selectorText).get());
|
||||
value = value->mNext;
|
||||
|
@ -459,45 +480,44 @@ RuleHash::~RuleHash(void)
|
|||
PL_FinishArenaPool(&mArena);
|
||||
}
|
||||
|
||||
void RuleHash::PrependRuleToTable(PLDHashTable* aTable,
|
||||
const void* aKey, nsICSSStyleRule* aRule)
|
||||
void RuleHash::PrependRuleToTable(PLDHashTable* aTable, const void* aKey,
|
||||
RuleValue* aRuleInfo)
|
||||
{
|
||||
// Get a new or existing entry.
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*,
|
||||
PL_DHashTableOperate(aTable, aKey, PL_DHASH_ADD));
|
||||
if (!entry)
|
||||
return;
|
||||
entry->mRules = new (mArena) RuleValue(aRule, mRuleCount++, entry->mRules);
|
||||
entry->mRules = aRuleInfo->Add(mRuleCount++, entry->mRules);
|
||||
}
|
||||
|
||||
void RuleHash::PrependUniversalRule(nsICSSStyleRule* aRule)
|
||||
void RuleHash::PrependUniversalRule(RuleValue *aRuleInfo)
|
||||
{
|
||||
mUniversalRules =
|
||||
new (mArena) RuleValue(aRule, mRuleCount++, mUniversalRules);
|
||||
mUniversalRules = aRuleInfo->Add(mRuleCount++, mUniversalRules);
|
||||
}
|
||||
|
||||
void RuleHash::PrependRule(nsICSSStyleRule* aRule)
|
||||
void RuleHash::PrependRule(RuleValue *aRuleInfo)
|
||||
{
|
||||
nsCSSSelector* selector = aRule->FirstSelector();
|
||||
nsCSSSelector *selector = aRuleInfo->mSelector;
|
||||
if (nsnull != selector->mIDList) {
|
||||
PrependRuleToTable(&mIdTable, selector->mIDList->mAtom, aRule);
|
||||
PrependRuleToTable(&mIdTable, selector->mIDList->mAtom, aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mIdSelectors);
|
||||
}
|
||||
else if (nsnull != selector->mClassList) {
|
||||
PrependRuleToTable(&mClassTable, selector->mClassList->mAtom, aRule);
|
||||
PrependRuleToTable(&mClassTable, selector->mClassList->mAtom, aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mClassSelectors);
|
||||
}
|
||||
else if (nsnull != selector->mTag) {
|
||||
PrependRuleToTable(&mTagTable, selector->mTag, aRule);
|
||||
PrependRuleToTable(&mTagTable, selector->mTag, aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mTagSelectors);
|
||||
}
|
||||
else if (kNameSpaceID_Unknown != selector->mNameSpace) {
|
||||
PrependRuleToTable(&mNameSpaceTable,
|
||||
NS_INT32_TO_PTR(selector->mNameSpace), aRule);
|
||||
NS_INT32_TO_PTR(selector->mNameSpace), aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mNameSpaceSelectors);
|
||||
}
|
||||
else { // universal tag selector
|
||||
PrependUniversalRule(aRule);
|
||||
PrependUniversalRule(aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mUniversalSelectors);
|
||||
}
|
||||
}
|
||||
|
@ -593,15 +613,16 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
|
|||
highestRuleIndex = ruleIndex;
|
||||
}
|
||||
}
|
||||
(*aFunc)(mEnumList[valueIndex]->mRule, aData);
|
||||
RuleValue *next = mEnumList[valueIndex]->mNext;
|
||||
RuleValue *cur = mEnumList[valueIndex];
|
||||
(*aFunc)(cur->mRule, cur->mSelector, aData);
|
||||
RuleValue *next = cur->mNext;
|
||||
mEnumList[valueIndex] = next ? next : mEnumList[--valueCount];
|
||||
}
|
||||
|
||||
// Fast loop over single value.
|
||||
RuleValue* value = mEnumList[0];
|
||||
do {
|
||||
(*aFunc)(value->mRule, aData);
|
||||
(*aFunc)(value->mRule, value->mSelector, aData);
|
||||
value = value->mNext;
|
||||
} while (value);
|
||||
}
|
||||
|
@ -617,7 +638,7 @@ void RuleHash::EnumerateTagRules(nsIAtom* aTag, RuleEnumFunc aFunc, void* aData)
|
|||
RuleValue *tagValue = entry->mRules;
|
||||
do {
|
||||
RULE_HASH_STAT_INCREMENT(mPseudoTagCalls);
|
||||
(*aFunc)(tagValue->mRule, aData);
|
||||
(*aFunc)(tagValue->mRule, tagValue->mSelector, aData);
|
||||
tagValue = tagValue->mNext;
|
||||
} while (tagValue);
|
||||
}
|
||||
|
@ -656,23 +677,19 @@ static PLDHashTableOps AttributeSelectorOps = {
|
|||
|
||||
struct RuleCascadeData {
|
||||
RuleCascadeData(nsIAtom *aMedium, PRBool aQuirksMode)
|
||||
: mWeightedRules(nsnull),
|
||||
mRuleHash(aQuirksMode),
|
||||
: mRuleHash(aQuirksMode),
|
||||
mStateSelectors(),
|
||||
mMedium(aMedium),
|
||||
mNext(nsnull)
|
||||
{
|
||||
NS_NewISupportsArray(&mWeightedRules);
|
||||
PL_DHashTableInit(&mAttributeSelectors, &AttributeSelectorOps, nsnull,
|
||||
sizeof(AttributeSelectorEntry), 16);
|
||||
}
|
||||
|
||||
~RuleCascadeData(void)
|
||||
{
|
||||
NS_IF_RELEASE(mWeightedRules);
|
||||
PL_DHashTableFinish(&mAttributeSelectors);
|
||||
}
|
||||
nsISupportsArray* mWeightedRules;
|
||||
RuleHash mRuleHash;
|
||||
nsVoidArray mStateSelectors;
|
||||
PLDHashTable mAttributeSelectors; // nsIAtom* -> nsVoidArray*
|
||||
|
@ -3880,14 +3897,14 @@ static PRBool SelectorMatchesTree(RuleProcessorData &data,
|
|||
return PRBool(nsnull == selector); // matches if ran out of selectors
|
||||
}
|
||||
|
||||
static void ContentEnumFunc(nsICSSStyleRule* aRule, void* aData)
|
||||
static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
|
||||
void* aData)
|
||||
{
|
||||
ElementRuleProcessorData* data = (ElementRuleProcessorData*)aData;
|
||||
|
||||
nsCSSSelector* selector = aRule->FirstSelector();
|
||||
if (SelectorMatches(*data, selector, 0, nsnull, 0)) {
|
||||
selector = selector->mNext;
|
||||
if (SelectorMatchesTree(*data, selector)) {
|
||||
if (SelectorMatches(*data, aSelector, 0, nsnull, 0)) {
|
||||
nsCSSSelector *next = aSelector->mNext;
|
||||
if (!next || SelectorMatchesTree(*data, next)) {
|
||||
// for performance, require that every implementation of
|
||||
// nsICSSStyleRule return the same pointer for nsIStyleRule (why
|
||||
// would anything multiply inherit nsIStyleRule anyway?)
|
||||
|
@ -3923,19 +3940,18 @@ CSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void PseudoEnumFunc(nsICSSStyleRule* aRule, void* aData)
|
||||
static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
|
||||
void* aData)
|
||||
{
|
||||
PseudoRuleProcessorData* data = (PseudoRuleProcessorData*)aData;
|
||||
|
||||
nsCSSSelector* selector = aRule->FirstSelector();
|
||||
|
||||
NS_ASSERTION(selector->mTag == data->mPseudoTag, "RuleHash failure");
|
||||
NS_ASSERTION(aSelector->mTag == data->mPseudoTag, "RuleHash failure");
|
||||
PRBool matches = PR_TRUE;
|
||||
if (data->mComparator)
|
||||
data->mComparator->PseudoMatches(data->mPseudoTag, selector, &matches);
|
||||
data->mComparator->PseudoMatches(data->mPseudoTag, aSelector, &matches);
|
||||
|
||||
if (matches) {
|
||||
selector = selector->mNext;
|
||||
nsCSSSelector *selector = aSelector->mNext;
|
||||
|
||||
if (selector) { // test next selector specially
|
||||
if (PRUnichar('+') == selector->mOperator) {
|
||||
|
@ -4113,17 +4129,17 @@ PRBool IsStateSelector(nsCSSSelector& aSelector)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
AddRule(nsISupports* aRule, void* aCascade)
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
AddRule(void* aRuleInfo, void* aCascade)
|
||||
{
|
||||
nsICSSStyleRule* rule = NS_STATIC_CAST(nsICSSStyleRule*, aRule);
|
||||
RuleValue* ruleInfo = NS_STATIC_CAST(RuleValue*, aRuleInfo);
|
||||
RuleCascadeData *cascade = NS_STATIC_CAST(RuleCascadeData*, aCascade);
|
||||
|
||||
// Build the rule hash.
|
||||
cascade->mRuleHash.PrependRule(rule);
|
||||
cascade->mRuleHash.PrependRule(ruleInfo);
|
||||
|
||||
nsVoidArray* stateArray = &cascade->mStateSelectors;
|
||||
for (nsCSSSelector* selector = rule->FirstSelector();
|
||||
for (nsCSSSelector* selector = ruleInfo->mSelector;
|
||||
selector; selector = selector->mNext) {
|
||||
// Build mStateSelectors.
|
||||
if (IsStateSelector(*selector))
|
||||
|
@ -4153,15 +4169,24 @@ AddRule(nsISupports* aRule, void* aCascade)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
RuleArraysDestroy(nsHashKey *aKey, void *aData, void *aClosure)
|
||||
{
|
||||
delete NS_STATIC_CAST(nsAutoVoidArray*, aData);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
struct CascadeEnumData {
|
||||
CascadeEnumData(nsIAtom* aMedium)
|
||||
CascadeEnumData(nsIAtom* aMedium, PLArenaPool& aArena)
|
||||
: mMedium(aMedium),
|
||||
mRuleArrays(64)
|
||||
mRuleArrays(nsnull, nsnull, RuleArraysDestroy, nsnull, 64),
|
||||
mArena(aArena)
|
||||
{
|
||||
}
|
||||
|
||||
nsIAtom* mMedium;
|
||||
nsSupportsHashtable mRuleArrays; // of nsISupportsArray
|
||||
nsObjectHashtable mRuleArrays; // of nsAutoVoidArray
|
||||
PLArenaPool& mArena;
|
||||
};
|
||||
|
||||
static PRBool
|
||||
|
@ -4175,16 +4200,21 @@ InsertRuleByWeight(nsISupports* aRule, void* aData)
|
|||
if (nsICSSRule::STYLE_RULE == type) {
|
||||
nsICSSStyleRule* styleRule = (nsICSSStyleRule*)rule;
|
||||
|
||||
PRInt32 weight = styleRule->GetWeight();
|
||||
nsPRUint32Key key(weight);
|
||||
nsCOMPtr<nsISupportsArray> rules(dont_AddRef(
|
||||
NS_STATIC_CAST(nsISupportsArray*, data->mRuleArrays.Get(&key))));
|
||||
if (!rules) {
|
||||
NS_NewISupportsArray(getter_AddRefs(rules));
|
||||
if (!rules) return PR_FALSE; // out of memory
|
||||
data->mRuleArrays.Put(&key, rules);
|
||||
for (nsCSSSelectorList *sel = styleRule->Selector();
|
||||
sel; sel = sel->mNext) {
|
||||
PRInt32 weight = sel->mWeight;
|
||||
nsPRUint32Key key(weight);
|
||||
nsAutoVoidArray *rules =
|
||||
NS_STATIC_CAST(nsAutoVoidArray*, data->mRuleArrays.Get(&key));
|
||||
if (!rules) {
|
||||
rules = new nsAutoVoidArray();
|
||||
if (!rules) return PR_FALSE; // out of memory
|
||||
data->mRuleArrays.Put(&key, rules);
|
||||
}
|
||||
RuleValue *info =
|
||||
new (data->mArena) RuleValue(styleRule, sel->mSelectors);
|
||||
rules->AppendElement(info);
|
||||
}
|
||||
rules->AppendElement(styleRule);
|
||||
}
|
||||
else if (nsICSSRule::MEDIA_RULE == type) {
|
||||
nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule;
|
||||
|
@ -4221,7 +4251,7 @@ CSSRuleProcessor::CascadeSheetRulesInto(nsISupports* aSheet, void* aData)
|
|||
|
||||
struct RuleArrayData {
|
||||
PRInt32 mWeight;
|
||||
nsISupportsArray* mRuleArray;
|
||||
nsVoidArray* mRuleArray;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(int) CompareArrayData(const void* aArg1, const void* aArg2,
|
||||
|
@ -4243,11 +4273,11 @@ struct FillArrayData {
|
|||
RuleArrayData* mArrayData;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool) FillArray(nsHashKey* aKey, void* aData,
|
||||
void* aClosure)
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
FillArray(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
{
|
||||
nsPRUint32Key* key = NS_STATIC_CAST(nsPRUint32Key*, aKey);
|
||||
nsISupportsArray* weightArray = NS_STATIC_CAST(nsISupportsArray*, aData);
|
||||
nsVoidArray* weightArray = NS_STATIC_CAST(nsVoidArray*, aData);
|
||||
FillArrayData* data = NS_STATIC_CAST(FillArrayData*, aClosure);
|
||||
|
||||
RuleArrayData& ruleData = data->mArrayData[data->mIndex++];
|
||||
|
@ -4262,8 +4292,8 @@ PR_STATIC_CALLBACK(PRBool) FillArray(nsHashKey* aKey, void* aData,
|
|||
* puts them all in one big array which has a primary sort by weight
|
||||
* and secondary sort by order.
|
||||
*/
|
||||
static void PutRulesInList(nsSupportsHashtable* aRuleArrays,
|
||||
nsISupportsArray* aWeightedRules)
|
||||
static void PutRulesInList(nsObjectHashtable* aRuleArrays,
|
||||
nsVoidArray* aWeightedRules)
|
||||
{
|
||||
PRInt32 arrayCount = aRuleArrays->Count();
|
||||
RuleArrayData* arrayData = new RuleArrayData[arrayCount];
|
||||
|
@ -4272,7 +4302,7 @@ static void PutRulesInList(nsSupportsHashtable* aRuleArrays,
|
|||
NS_QuickSort(arrayData, arrayCount, sizeof(RuleArrayData),
|
||||
CompareArrayData, nsnull);
|
||||
for (PRInt32 i = 0; i < arrayCount; ++i)
|
||||
aWeightedRules->AppendElements(arrayData[i].mRuleArray);
|
||||
aWeightedRules->AppendElements(*arrayData[i].mRuleArray);
|
||||
|
||||
delete [] arrayData;
|
||||
}
|
||||
|
@ -4295,11 +4325,12 @@ CSSRuleProcessor::GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium)
|
|||
cascade = new RuleCascadeData(aMedium,
|
||||
eCompatibility_NavQuirks == quirkMode);
|
||||
if (cascade) {
|
||||
CascadeEnumData data(aMedium);
|
||||
CascadeEnumData data(aMedium, cascade->mRuleHash.Arena());
|
||||
mSheets->EnumerateForwards(CascadeSheetRulesInto, &data);
|
||||
PutRulesInList(&data.mRuleArrays, cascade->mWeightedRules);
|
||||
nsVoidArray weightedRules;
|
||||
PutRulesInList(&data.mRuleArrays, &weightedRules);
|
||||
|
||||
if (!cascade->mWeightedRules->EnumerateBackwards(AddRule, cascade)) {
|
||||
if (!weightedRules.EnumerateBackwards(AddRule, cascade)) {
|
||||
delete cascade;
|
||||
cascade = nsnull;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration* aDecl,
|
|||
NS_PRECONDITION(aDecl, "Null decl!");
|
||||
|
||||
nsCOMPtr<nsICSSStyleRule> cssRule;
|
||||
nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsCSSSelector());
|
||||
nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (!aDeclOwnedByRule) {
|
||||
aDecl->RuleAbort();
|
||||
|
@ -121,7 +121,6 @@ nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration* aDecl,
|
|||
}
|
||||
|
||||
cssRule->SetDeclaration(aDecl);
|
||||
cssRule->SetWeight(PR_INT32_MAX);
|
||||
return mContent->SetHTMLAttribute(nsHTMLAtoms::style,
|
||||
nsHTMLValue(cssRule),
|
||||
aNotify);
|
||||
|
|
|
@ -130,12 +130,14 @@ public:
|
|||
|
||||
PRInt32 CalcWeight(void) const;
|
||||
|
||||
nsresult ToString( nsAString& aString, nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsPseudoElem, PRInt8 aNegatedIndex ) const;
|
||||
void ToString(nsAString& aString, nsICSSStyleSheet* aSheet) const;
|
||||
|
||||
private:
|
||||
|
||||
void AppendNegationToString(nsAString& aString);
|
||||
void ToStringInternal(nsAString& aString, nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsPseudoElem,
|
||||
PRIntn aNegatedIndex) const;
|
||||
|
||||
public:
|
||||
PRInt32 mNameSpace;
|
||||
|
@ -151,6 +153,38 @@ public:
|
|||
nsCSSSelector* mNext;
|
||||
};
|
||||
|
||||
/**
|
||||
* A selector list is the unit of selectors that each style rule has.
|
||||
* For example, "P B, H1 B { ... }" would be a selector list with two
|
||||
* items (where each |nsCSSSelectorList| object's |mSelectors| has
|
||||
* an |mNext| for the P or H1). We represent them as linked lists.
|
||||
*/
|
||||
struct nsCSSSelectorList {
|
||||
nsCSSSelectorList(void);
|
||||
~nsCSSSelectorList(void);
|
||||
|
||||
/**
|
||||
* Push a copy of |aSelector| on to the beginning of |mSelectors|,
|
||||
* setting its |mNext| to the current value of |mSelectors|.
|
||||
*
|
||||
* The caller is responsible for updating |mWeight|.
|
||||
*/
|
||||
void AddSelector(const nsCSSSelector& aSelector);
|
||||
|
||||
/**
|
||||
* Should be used only on the first in the list
|
||||
*/
|
||||
void ToString(nsAString& aResult, nsICSSStyleSheet* aSheet);
|
||||
|
||||
/**
|
||||
* Do a deep clone. Should be used only on the first in the list.
|
||||
*/
|
||||
nsCSSSelectorList* Clone();
|
||||
|
||||
nsCSSSelector* mSelectors;
|
||||
PRInt32 mWeight;
|
||||
nsCSSSelectorList* mNext;
|
||||
};
|
||||
|
||||
// IID for the nsICSSStyleRule interface {7c277af0-af19-11d1-8031-006008159b5a}
|
||||
#define NS_ICSS_STYLE_RULE_IID \
|
||||
|
@ -160,11 +194,8 @@ class nsICSSStyleRule : public nsICSSRule {
|
|||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICSS_STYLE_RULE_IID)
|
||||
|
||||
virtual nsCSSSelector* FirstSelector(void) = 0;
|
||||
virtual void AddSelector(const nsCSSSelector& aSelector) = 0;
|
||||
virtual void DeleteSelector(nsCSSSelector* aSelector) = 0;
|
||||
virtual void SetSourceSelectorText(const nsString& aSelectorText) = 0;
|
||||
virtual void GetSourceSelectorText(nsString& aSelectorText) const = 0;
|
||||
// null for style attribute
|
||||
virtual nsCSSSelectorList* Selector(void) = 0;
|
||||
|
||||
virtual PRUint32 GetLineNumber(void) const = 0;
|
||||
virtual void SetLineNumber(PRUint32 aLineNumber) = 0;
|
||||
|
@ -172,9 +203,6 @@ public:
|
|||
virtual nsCSSDeclaration* GetDeclaration(void) const = 0;
|
||||
virtual void SetDeclaration(nsCSSDeclaration* aDeclaration) = 0;
|
||||
|
||||
virtual PRInt32 GetWeight(void) const = 0;
|
||||
virtual void SetWeight(PRInt32 aWeight) = 0;
|
||||
|
||||
virtual already_AddRefed<nsIStyleRule> GetImportantRule(void) = 0;
|
||||
|
||||
// Hook for inspector.
|
||||
|
@ -183,6 +211,6 @@ public:
|
|||
|
||||
nsresult
|
||||
NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult,
|
||||
const nsCSSSelector& aSelector);
|
||||
nsCSSSelectorList* aSelector);
|
||||
|
||||
#endif /* nsICSSStyleRule_h___ */
|
||||
|
|
|
@ -51,7 +51,6 @@ interface inIDOMUtils : nsISupports
|
|||
{
|
||||
// CSS utilities
|
||||
nsISupportsArray getStyleRules(in nsIDOMElement aElement);
|
||||
unsigned long getRuleWeight(in nsIDOMCSSStyleRule aRule);
|
||||
unsigned long getRuleLine(in nsIDOMCSSStyleRule aRule);
|
||||
|
||||
// DOM Node utilities
|
||||
|
|
|
@ -150,16 +150,6 @@ inDOMUtils::GetStyleRules(nsIDOMElement *aElement, nsISupportsArray **_retval)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
inDOMUtils::GetRuleWeight(nsIDOMCSSStyleRule *aRule, PRUint32 *_retval)
|
||||
{
|
||||
if (!aRule) return NS_OK;
|
||||
nsCOMPtr<nsIDOMCSSStyleRule> rule = aRule;
|
||||
nsCOMPtr<nsICSSStyleRule> cssrule = do_QueryInterface(rule);
|
||||
*_retval = cssrule->GetWeight();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
inDOMUtils::GetRuleLine(nsIDOMCSSStyleRule *aRule, PRUint32 *_retval)
|
||||
{
|
||||
|
|
|
@ -394,10 +394,6 @@ function(aRow, aColId)
|
|||
return rule.parentStyleSheet ? rule.parentStyleSheet.href : "";
|
||||
}
|
||||
|
||||
if (aColId == "olcWeight") {
|
||||
return rule.type == CSSRule.STYLE_RULE ? this.mDOMUtils.getRuleWeight(rule) : "";
|
||||
}
|
||||
|
||||
if (aColId == "olcLine") {
|
||||
return rule.type == CSSRule.STYLE_RULE ? this.mDOMUtils.getRuleLine(rule) : "";
|
||||
}
|
||||
|
|
|
@ -50,8 +50,6 @@
|
|||
<splitter class="tree-splitter"/>
|
||||
<treecol id="olcFileURL" label="&styleRuleURI.label;" flex="1"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="olcWeight" label="&styleRuleWeight.label;"/>
|
||||
<splitter class="tree-splitter"/>
|
||||
<treecol id="olcLine" label="&styleRuleLineNumber.label;"/>
|
||||
</treecols>
|
||||
<treechildren id="olbStyleRules"/>
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
|
||||
<!ENTITY styleRule.label "Rule">
|
||||
<!ENTITY styleRuleURI.label "File">
|
||||
<!ENTITY styleRuleWeight.label "Weight">
|
||||
<!ENTITY styleRuleLineNumber.label "Line">
|
||||
|
||||
<!ENTITY styleRulePropPriority.label "Priority">
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
|
||||
/* ::::: default column widths ::::: */
|
||||
|
||||
#olcWeight,
|
||||
#olcLine {
|
||||
width: 5em;
|
||||
}
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
|
||||
/* ::::: default column widths ::::: */
|
||||
|
||||
#olcWeight,
|
||||
#olcLine {
|
||||
width: 5em;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include "nsICSSStyleSheet.h"
|
||||
#include "nsIDOMCSSStyleSheet.h"
|
||||
#include "nsICSSRule.h"
|
||||
#include "nsICSSStyleRule.h"
|
||||
#include "nsIDOMCSSStyleRule.h"
|
||||
#include "nsStyleChangeList.h"
|
||||
#include "nsIFrameManager.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
@ -670,8 +670,8 @@ nsMathMLFrame::MapAttributesIntoCSS(nsIPresContext* aPresContext,
|
|||
nsAutoString tmpSelector;
|
||||
nsCOMPtr<nsICSSRule> tmpRule;
|
||||
cssSheet->GetStyleRuleAt(k, *getter_AddRefs(tmpRule));
|
||||
nsCOMPtr<nsICSSStyleRule> tmpStyleRule(do_QueryInterface(tmpRule));
|
||||
tmpStyleRule->GetSourceSelectorText(tmpSelector);
|
||||
nsCOMPtr<nsIDOMCSSStyleRule> tmpStyleRule(do_QueryInterface(tmpRule));
|
||||
tmpStyleRule->GetSelectorText(tmpSelector);
|
||||
if (tmpSelector.Equals(selector)) {
|
||||
k = -1;
|
||||
break;
|
||||
|
|
|
@ -87,62 +87,6 @@
|
|||
|
||||
//#define ENABLE_COUNTERS // un-comment this to enable counters (bug 15174)
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(SelectorList)
|
||||
|
||||
// e.g. "P B, H1 B { ... }" has a selector list with two elements,
|
||||
// each of which has two selectors.
|
||||
struct SelectorList {
|
||||
SelectorList(void);
|
||||
~SelectorList(void);
|
||||
|
||||
void AddSelector(const nsCSSSelector& aSelector);
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
void Dump(void);
|
||||
#endif
|
||||
|
||||
nsCSSSelector* mSelectors;
|
||||
PRInt32 mWeight;
|
||||
SelectorList* mNext;
|
||||
};
|
||||
|
||||
SelectorList::SelectorList(void)
|
||||
: mSelectors(nsnull),
|
||||
mNext(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(SelectorList);
|
||||
}
|
||||
|
||||
SelectorList::~SelectorList()
|
||||
{
|
||||
MOZ_COUNT_DTOR(SelectorList);
|
||||
nsCSSSelector* sel = mSelectors;
|
||||
while (nsnull != sel) {
|
||||
nsCSSSelector* dead = sel;
|
||||
sel = sel->mNext;
|
||||
delete dead;
|
||||
}
|
||||
if (nsnull != mNext) {
|
||||
delete mNext;
|
||||
}
|
||||
}
|
||||
|
||||
void SelectorList::AddSelector(const nsCSSSelector& aSelector)
|
||||
{ // prepend to list
|
||||
nsCSSSelector* newSel = new nsCSSSelector(aSelector);
|
||||
if (nsnull != newSel) {
|
||||
newSel->mNext = mSelectors;
|
||||
mSelectors = newSel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
void SelectorList::Dump()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Your basic top-down recursive descent style parser
|
||||
|
@ -240,8 +184,8 @@ protected:
|
|||
void ParseLangSelector(nsCSSSelector& aSelector, PRInt32& aParsingStatus,
|
||||
PRInt32& aErrorCode);
|
||||
|
||||
PRBool ParseSelectorList(PRInt32& aErrorCode, SelectorList*& aListHead);
|
||||
PRBool ParseSelectorGroup(PRInt32& aErrorCode, SelectorList*& aListHead);
|
||||
PRBool ParseSelectorList(PRInt32& aErrorCode, nsCSSSelectorList*& aListHead);
|
||||
PRBool ParseSelectorGroup(PRInt32& aErrorCode, nsCSSSelectorList*& aListHead);
|
||||
PRBool ParseSelector(PRInt32& aErrorCode, nsCSSSelector& aSelectorResult);
|
||||
nsCSSDeclaration* ParseDeclarationBlock(PRInt32& aErrorCode,
|
||||
PRBool aCheckForBraces);
|
||||
|
@ -692,12 +636,15 @@ CSSParserImpl::ParseStyleAttribute(const nsAString& aAttributeValue,
|
|||
haveBraces = PR_FALSE;
|
||||
}
|
||||
|
||||
nsCSSDeclaration* declaration =
|
||||
ParseDeclarationBlock(errorCode, haveBraces);
|
||||
if (nsnull != declaration) {
|
||||
nsCSSDeclaration* declaration = ParseDeclarationBlock(errorCode, haveBraces);
|
||||
if (declaration) {
|
||||
// Create a style rule for the delcaration
|
||||
nsICSSStyleRule* rule = nsnull;
|
||||
NS_NewCSSStyleRule(&rule, nsCSSSelector());
|
||||
rv = NS_NewCSSStyleRule(&rule, nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
declaration->RuleAbort();
|
||||
return rv;
|
||||
}
|
||||
rule->SetDeclaration(declaration);
|
||||
*aResult = rule;
|
||||
}
|
||||
|
@ -1496,7 +1443,7 @@ void CSSParserImpl::AppendRule(nsICSSRule* aRule)
|
|||
PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode, RuleAppendFunc aAppendFunc, void* aData)
|
||||
{
|
||||
// First get the list of selectors for the rule
|
||||
SelectorList* slist = nsnull;
|
||||
nsCSSSelectorList* slist = nsnull;
|
||||
PRUint32 linenum = mScanner->GetLineNumber();
|
||||
if (! ParseSelectorList(aErrorCode, slist)) {
|
||||
REPORT_UNEXPECTED(
|
||||
|
@ -1525,38 +1472,24 @@ PRBool CSSParserImpl::ParseRuleSet(PRInt32& aErrorCode, RuleAppendFunc aAppendFu
|
|||
|
||||
// Translate the selector list and declaration block into style data
|
||||
|
||||
SelectorList* list = slist;
|
||||
|
||||
while (nsnull != list) {
|
||||
nsICSSStyleRule* rule = nsnull;
|
||||
|
||||
NS_NewCSSStyleRule(&rule, *(list->mSelectors));
|
||||
if (nsnull != rule) {
|
||||
if (nsnull != list->mSelectors->mNext) { // hand off other selectors to new rule
|
||||
nsCSSSelector* ruleFirst = rule->FirstSelector();
|
||||
ruleFirst->mNext = list->mSelectors->mNext;
|
||||
list->mSelectors->mNext = nsnull;
|
||||
}
|
||||
rule->SetLineNumber(linenum);
|
||||
rule->SetDeclaration(declaration);
|
||||
rule->SetWeight(list->mWeight);
|
||||
// rule->List();
|
||||
(*aAppendFunc)(rule, aData);
|
||||
NS_RELEASE(rule);
|
||||
}
|
||||
|
||||
list = list->mNext;
|
||||
nsCOMPtr<nsICSSStyleRule> rule;
|
||||
NS_NewCSSStyleRule(getter_AddRefs(rule), slist);
|
||||
if (!rule) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
delete slist;
|
||||
return PR_FALSE;
|
||||
}
|
||||
rule->SetLineNumber(linenum);
|
||||
rule->SetDeclaration(declaration);
|
||||
(*aAppendFunc)(rule, aData);
|
||||
|
||||
// Release temporary storage
|
||||
delete slist;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
|
||||
SelectorList*& aListHead)
|
||||
nsCSSSelectorList*& aListHead)
|
||||
{
|
||||
SelectorList* list = nsnull;
|
||||
nsCSSSelectorList* list = nsnull;
|
||||
if (! ParseSelectorGroup(aErrorCode, list)) {
|
||||
// must have at least one selector group
|
||||
aListHead = nsnull;
|
||||
|
@ -1575,7 +1508,7 @@ PRBool CSSParserImpl::ParseSelectorList(PRInt32& aErrorCode,
|
|||
|
||||
if (eCSSToken_Symbol == tk->mType) {
|
||||
if (',' == tk->mSymbol) {
|
||||
SelectorList* newList = nsnull;
|
||||
nsCSSSelectorList* newList = nsnull;
|
||||
// Another selector group must follow
|
||||
if (! ParseSelectorGroup(aErrorCode, newList)) {
|
||||
break;
|
||||
|
@ -1627,9 +1560,9 @@ static PRBool IsTreePseudoElement(nsIAtom* aPseudo)
|
|||
#endif
|
||||
|
||||
PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
|
||||
SelectorList*& aList)
|
||||
nsCSSSelectorList*& aList)
|
||||
{
|
||||
SelectorList* list = nsnull;
|
||||
nsCSSSelectorList* list = nsnull;
|
||||
PRUnichar combinator = PRUnichar(0);
|
||||
PRInt32 weight = 0;
|
||||
PRBool havePseudoElement = PR_FALSE;
|
||||
|
@ -1639,7 +1572,7 @@ PRBool CSSParserImpl::ParseSelectorGroup(PRInt32& aErrorCode,
|
|||
break;
|
||||
}
|
||||
if (nsnull == list) {
|
||||
list = new SelectorList();
|
||||
list = new nsCSSSelectorList();
|
||||
if (nsnull == list) {
|
||||
aErrorCode = NS_ERROR_OUT_OF_MEMORY;
|
||||
return PR_FALSE;
|
||||
|
|
|
@ -537,8 +537,16 @@ void nsCSSSelector::AppendNegationToString(nsAString& aString)
|
|||
// Builds the textual representation of a selector. Called by DOM 2 CSS
|
||||
// StyleRule:selectorText
|
||||
//
|
||||
nsresult nsCSSSelector::ToString( nsAString& aString, nsICSSStyleSheet* aSheet, PRBool aIsPseudoElem,
|
||||
PRInt8 aNegatedIndex) const
|
||||
void
|
||||
nsCSSSelector::ToString(nsAString& aString, nsICSSStyleSheet* aSheet) const
|
||||
{
|
||||
ToStringInternal(aString, aSheet, IsPseudoElement(mTag), 0);
|
||||
}
|
||||
|
||||
void nsCSSSelector::ToStringInternal(nsAString& aString,
|
||||
nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsPseudoElem,
|
||||
PRIntn aNegatedIndex) const
|
||||
{
|
||||
nsAutoString temp;
|
||||
PRBool aIsNegated = PRBool(0 < aNegatedIndex);
|
||||
|
@ -546,7 +554,7 @@ nsresult nsCSSSelector::ToString( nsAString& aString, nsICSSStyleSheet* aSheet,
|
|||
// 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->ToString(aString, aSheet, IsPseudoElement(mTag), PR_FALSE);
|
||||
mNext->ToStringInternal(aString, aSheet, IsPseudoElement(mTag), 0);
|
||||
if (!aIsNegated && !IsPseudoElement(mTag)) {
|
||||
// don't add a leading whitespace if we have a pseudo-element
|
||||
// or a negated simple selector
|
||||
|
@ -685,7 +693,7 @@ nsresult nsCSSSelector::ToString( nsAString& aString, nsICSSStyleSheet* aSheet,
|
|||
|
||||
if (mNegations) {
|
||||
// chain all the negated selectors
|
||||
mNegations->ToString(aString, aSheet, PR_FALSE, aNegatedIndex + 1);
|
||||
mNegations->ToStringInternal(aString, aSheet, PR_FALSE, aNegatedIndex + 1);
|
||||
}
|
||||
|
||||
// Append the operator only if the selector is not negated and is not
|
||||
|
@ -694,9 +702,82 @@ nsresult nsCSSSelector::ToString( nsAString& aString, nsICSSStyleSheet* aSheet,
|
|||
aString.Append(PRUnichar(' '));
|
||||
aString.Append(mOperator);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// -- nsCSSSelectorList -------------------------------
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsCSSSelectorList)
|
||||
|
||||
nsCSSSelectorList::nsCSSSelectorList(void)
|
||||
: mSelectors(nsnull),
|
||||
mNext(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsCSSSelectorList);
|
||||
}
|
||||
|
||||
nsCSSSelectorList::~nsCSSSelectorList()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsCSSSelectorList);
|
||||
nsCSSSelector* sel = mSelectors;
|
||||
while (sel) {
|
||||
nsCSSSelector* dead = sel;
|
||||
sel = sel->mNext;
|
||||
delete dead;
|
||||
}
|
||||
if (mNext) {
|
||||
delete mNext;
|
||||
}
|
||||
}
|
||||
|
||||
void nsCSSSelectorList::AddSelector(const nsCSSSelector& aSelector)
|
||||
{ // prepend to list
|
||||
nsCSSSelector* newSel = new nsCSSSelector(aSelector);
|
||||
if (newSel) {
|
||||
newSel->mNext = mSelectors;
|
||||
mSelectors = newSel;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSSelectorList::ToString(nsAString& aResult, nsICSSStyleSheet* aSheet)
|
||||
{
|
||||
nsCSSSelectorList *p = this;
|
||||
for (;;) {
|
||||
p->mSelectors->ToString(aResult, aSheet);
|
||||
p = p->mNext;
|
||||
if (!p)
|
||||
break;
|
||||
aResult.Append(NS_LITERAL_STRING(", "));
|
||||
}
|
||||
}
|
||||
|
||||
nsCSSSelectorList*
|
||||
nsCSSSelectorList::Clone()
|
||||
{
|
||||
nsCSSSelectorList *list = nsnull;
|
||||
nsCSSSelectorList **list_cur = &list;
|
||||
for (nsCSSSelectorList *l = this; l; l = l->mNext) {
|
||||
nsCSSSelectorList *lcopy = new nsCSSSelectorList();
|
||||
if (!lcopy) {
|
||||
delete list;
|
||||
return nsnull;
|
||||
}
|
||||
*list_cur = lcopy;
|
||||
list_cur = &lcopy->mNext;
|
||||
|
||||
nsCSSSelector **sel_cur = &lcopy->mSelectors;
|
||||
for (nsCSSSelector *s = l->mSelectors; s; s = s->mNext) {
|
||||
nsCSSSelector *scopy = new nsCSSSelector(*s);
|
||||
if (!scopy) {
|
||||
delete list;
|
||||
return nsnull;
|
||||
}
|
||||
*sel_cur = scopy;
|
||||
sel_cur = &scopy->mNext;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// -- CSSImportantRule -------------------------------
|
||||
|
||||
|
@ -1046,16 +1127,12 @@ class CSSStyleRuleImpl : public nsCSSRule,
|
|||
public nsIDOMCSSStyleRule
|
||||
{
|
||||
public:
|
||||
CSSStyleRuleImpl(const nsCSSSelector& aSelector);
|
||||
CSSStyleRuleImpl(nsCSSSelectorList* aSelector);
|
||||
CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
virtual nsCSSSelector* FirstSelector(void);
|
||||
virtual void AddSelector(const nsCSSSelector& aSelector);
|
||||
virtual void DeleteSelector(nsCSSSelector* aSelector);
|
||||
virtual void SetSourceSelectorText(const nsString& aSelectorText);
|
||||
virtual void GetSourceSelectorText(nsString& aSelectorText) const;
|
||||
virtual nsCSSSelectorList* Selector(void);
|
||||
|
||||
virtual PRUint32 GetLineNumber(void) const;
|
||||
virtual void SetLineNumber(PRUint32 aLineNumber);
|
||||
|
@ -1063,9 +1140,6 @@ public:
|
|||
virtual nsCSSDeclaration* GetDeclaration(void) const;
|
||||
virtual void SetDeclaration(nsCSSDeclaration* aDeclaration);
|
||||
|
||||
virtual PRInt32 GetWeight(void) const;
|
||||
virtual void SetWeight(PRInt32 aWeight);
|
||||
|
||||
virtual already_AddRefed<nsIStyleRule> GetImportantRule(void);
|
||||
|
||||
// hook for inspector
|
||||
|
@ -1100,39 +1174,28 @@ protected:
|
|||
virtual ~CSSStyleRuleImpl(void);
|
||||
|
||||
protected:
|
||||
nsCSSSelector mSelector;
|
||||
nsCSSDeclaration* mDeclaration;
|
||||
PRInt32 mWeight;
|
||||
nsCSSSelectorList* mSelector; // null for style attribute
|
||||
nsCSSDeclaration* mDeclaration;
|
||||
CSSImportantRule* mImportantRule;
|
||||
DOMCSSDeclarationImpl* mDOMDeclaration;
|
||||
PRUint32 mLineNumber;
|
||||
};
|
||||
|
||||
CSSStyleRuleImpl::CSSStyleRuleImpl(const nsCSSSelector& aSelector)
|
||||
CSSStyleRuleImpl::CSSStyleRuleImpl(nsCSSSelectorList* aSelector)
|
||||
: nsCSSRule(),
|
||||
mSelector(aSelector), mDeclaration(nsnull),
|
||||
mWeight(0), mImportantRule(nsnull),
|
||||
mImportantRule(nsnull),
|
||||
mDOMDeclaration(nsnull)
|
||||
{
|
||||
}
|
||||
|
||||
CSSStyleRuleImpl::CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy)
|
||||
: nsCSSRule(aCopy),
|
||||
mSelector(aCopy.mSelector),
|
||||
mSelector(aCopy.mSelector ? aCopy.mSelector->Clone() : nsnull),
|
||||
mDeclaration(nsnull),
|
||||
mWeight(aCopy.mWeight),
|
||||
mImportantRule(nsnull),
|
||||
mDOMDeclaration(nsnull)
|
||||
{
|
||||
nsCSSSelector* copySel = aCopy.mSelector.mNext;
|
||||
nsCSSSelector* ourSel = &mSelector;
|
||||
|
||||
while (copySel && ourSel) {
|
||||
ourSel->mNext = new nsCSSSelector(*copySel);
|
||||
ourSel = ourSel->mNext;
|
||||
copySel = copySel->mNext;
|
||||
}
|
||||
|
||||
if (aCopy.mDeclaration) {
|
||||
mDeclaration = aCopy.mDeclaration->Clone();
|
||||
if (nsnull != mDeclaration) {
|
||||
|
@ -1145,12 +1208,9 @@ CSSStyleRuleImpl::CSSStyleRuleImpl(const CSSStyleRuleImpl& aCopy)
|
|||
|
||||
CSSStyleRuleImpl::~CSSStyleRuleImpl(void)
|
||||
{
|
||||
nsCSSSelector* next = mSelector.mNext;
|
||||
|
||||
while (nsnull != next) {
|
||||
nsCSSSelector* selector = next;
|
||||
next = selector->mNext;
|
||||
delete selector;
|
||||
if (mSelector) {
|
||||
delete mSelector;
|
||||
mSelector = nsnull;
|
||||
}
|
||||
if (nsnull != mDeclaration) {
|
||||
mDeclaration->Release();
|
||||
|
@ -1182,61 +1242,9 @@ NS_IMPL_ADDREF_INHERITED(CSSStyleRuleImpl, nsCSSRule);
|
|||
NS_IMPL_RELEASE_INHERITED(CSSStyleRuleImpl, nsCSSRule);
|
||||
|
||||
|
||||
nsCSSSelector* CSSStyleRuleImpl::FirstSelector(void)
|
||||
nsCSSSelectorList* CSSStyleRuleImpl::Selector(void)
|
||||
{
|
||||
return &mSelector;
|
||||
}
|
||||
|
||||
void CSSStyleRuleImpl::AddSelector(const nsCSSSelector& aSelector)
|
||||
{
|
||||
nsCSSSelector* selector = new nsCSSSelector(aSelector);
|
||||
nsCSSSelector* last = &mSelector;
|
||||
|
||||
while (nsnull != last->mNext) {
|
||||
last = last->mNext;
|
||||
}
|
||||
last->mNext = selector;
|
||||
}
|
||||
|
||||
|
||||
void CSSStyleRuleImpl::DeleteSelector(nsCSSSelector* aSelector)
|
||||
{
|
||||
if (nsnull != aSelector) {
|
||||
if (&mSelector == aSelector) { // handle first selector
|
||||
if (nsnull != mSelector.mNext) {
|
||||
nsCSSSelector* nextOne = mSelector.mNext;
|
||||
mSelector = *nextOne; // assign values
|
||||
mSelector.mNext = nextOne->mNext;
|
||||
delete nextOne;
|
||||
}
|
||||
else {
|
||||
mSelector.Reset();
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsCSSSelector* selector = &mSelector;
|
||||
|
||||
while (nsnull != selector->mNext) {
|
||||
if (aSelector == selector->mNext) {
|
||||
selector->mNext = aSelector->mNext;
|
||||
delete aSelector;
|
||||
return;
|
||||
}
|
||||
selector = selector->mNext;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSSStyleRuleImpl::SetSourceSelectorText(const nsString& aSelectorText)
|
||||
{
|
||||
/* no need for set, since get recreates the string */
|
||||
}
|
||||
|
||||
void CSSStyleRuleImpl::GetSourceSelectorText(nsString& aSelectorText) const
|
||||
{
|
||||
mSelector.ToString( aSelectorText, mSheet, IsPseudoElement(mSelector.mTag),
|
||||
0 );
|
||||
return mSelector;
|
||||
}
|
||||
|
||||
PRUint32 CSSStyleRuleImpl::GetLineNumber(void) const
|
||||
|
@ -1267,16 +1275,6 @@ void CSSStyleRuleImpl::SetDeclaration(nsCSSDeclaration* aDeclaration)
|
|||
}
|
||||
}
|
||||
|
||||
PRInt32 CSSStyleRuleImpl::GetWeight(void) const
|
||||
{
|
||||
return mWeight;
|
||||
}
|
||||
|
||||
void CSSStyleRuleImpl::SetWeight(PRInt32 aWeight)
|
||||
{
|
||||
mWeight = aWeight;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIStyleRule> CSSStyleRuleImpl::GetImportantRule(void)
|
||||
{
|
||||
if (!mImportantRule && mDeclaration) {
|
||||
|
@ -1349,10 +1347,9 @@ CSSStyleRuleImpl::List(FILE* out, PRInt32 aIndent) const
|
|||
for (PRInt32 index = aIndent; --index >= 0; ) fputs(" ", out);
|
||||
|
||||
nsAutoString buffer;
|
||||
mSelector.ToString(buffer, mSheet, PR_FALSE, 0);
|
||||
if (mSelector)
|
||||
mSelector->ToString(buffer, mSheet);
|
||||
|
||||
buffer.Append(NS_LITERAL_STRING(" weight: "));
|
||||
buffer.AppendInt(mWeight, 10);
|
||||
buffer.Append(NS_LITERAL_STRING(" "));
|
||||
fputs(NS_LossyConvertUCS2toASCII(buffer).get(), out);
|
||||
if (nsnull != mDeclaration) {
|
||||
|
@ -1378,9 +1375,10 @@ CSSStyleRuleImpl::GetType(PRUint16* aType)
|
|||
NS_IMETHODIMP
|
||||
CSSStyleRuleImpl::GetCssText(nsAString& aCssText)
|
||||
{
|
||||
mSelector.ToString( aCssText, mSheet, IsPseudoElement(mSelector.mTag),
|
||||
0 );
|
||||
aCssText.Append(PRUnichar(' '));
|
||||
if (mSelector) {
|
||||
mSelector->ToString(aCssText, mSheet);
|
||||
aCssText.Append(PRUnichar(' '));
|
||||
}
|
||||
aCssText.Append(PRUnichar('{'));
|
||||
aCssText.Append(PRUnichar(' '));
|
||||
if (mDeclaration)
|
||||
|
@ -1424,7 +1422,10 @@ CSSStyleRuleImpl::GetParentRule(nsIDOMCSSRule** aParentRule)
|
|||
NS_IMETHODIMP
|
||||
CSSStyleRuleImpl::GetSelectorText(nsAString& aSelectorText)
|
||||
{
|
||||
mSelector.ToString( aSelectorText, mSheet, IsPseudoElement(mSelector.mTag), 0 );
|
||||
if (mSelector)
|
||||
mSelector->ToString(aSelectorText, mSheet);
|
||||
else
|
||||
aSelectorText.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1456,7 +1457,7 @@ CSSStyleRuleImpl::GetStyle(nsIDOMCSSStyleDeclaration** aStyle)
|
|||
|
||||
nsresult
|
||||
NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult,
|
||||
const nsCSSSelector& aSelector)
|
||||
nsCSSSelectorList* aSelector)
|
||||
{
|
||||
if (aInstancePtrResult == nsnull) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
|
|
@ -105,9 +105,22 @@
|
|||
#include "nsIScriptSecurityManager.h"
|
||||
|
||||
struct RuleValue {
|
||||
RuleValue(nsICSSStyleRule* aRule, PRInt32 aIndex, RuleValue *aNext)
|
||||
: mRule(aRule), mIndex(aIndex), mNext(aNext) {}
|
||||
/**
|
||||
* |RuleValue|s are constructed before they become part of the
|
||||
* |RuleHash|, to act as rule/selector pairs. |Add| is called when
|
||||
* they are added to the |RuleHash|, and can be considered the second
|
||||
* half of the constructor.
|
||||
*/
|
||||
RuleValue(nsICSSStyleRule* aRule, nsCSSSelector* aSelector)
|
||||
: mRule(aRule), mSelector(aSelector) {}
|
||||
|
||||
RuleValue* Add(PRInt32 aIndex, RuleValue *aNext)
|
||||
{
|
||||
mIndex = aIndex;
|
||||
mNext = aNext;
|
||||
return this;
|
||||
}
|
||||
|
||||
// CAUTION: ~RuleValue will never get called as RuleValues are arena
|
||||
// allocated and arena cleanup will take care of deleting memory.
|
||||
// Add code to RuleHash::~RuleHash to get it to call the destructor
|
||||
|
@ -125,6 +138,7 @@ struct RuleValue {
|
|||
}
|
||||
|
||||
nsICSSStyleRule* mRule;
|
||||
nsCSSSelector* mSelector; // which of |mRule|'s selectors
|
||||
PRInt32 mIndex; // High index means low weight/order.
|
||||
RuleValue* mNext;
|
||||
};
|
||||
|
@ -189,28 +203,28 @@ PR_STATIC_CALLBACK(const void*)
|
|||
RuleHash_TagTable_GetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
||||
{
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*, hdr);
|
||||
return entry->mRules->mRule->FirstSelector()->mTag;
|
||||
return entry->mRules->mSelector->mTag;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(const void*)
|
||||
RuleHash_ClassTable_GetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
||||
{
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*, hdr);
|
||||
return entry->mRules->mRule->FirstSelector()->mClassList->mAtom;
|
||||
return entry->mRules->mSelector->mClassList->mAtom;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(const void*)
|
||||
RuleHash_IdTable_GetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
||||
{
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*, hdr);
|
||||
return entry->mRules->mRule->FirstSelector()->mIDList->mAtom;
|
||||
return entry->mRules->mSelector->mIDList->mAtom;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(const void*)
|
||||
RuleHash_NameSpaceTable_GetKey(PLDHashTable *table, PLDHashEntryHdr *hdr)
|
||||
{
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*, hdr);
|
||||
return NS_INT32_TO_PTR(entry->mRules->mRule->FirstSelector()->mNameSpace);
|
||||
return NS_INT32_TO_PTR(entry->mRules->mSelector->mNameSpace);
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PLDHashNumber)
|
||||
|
@ -228,7 +242,7 @@ RuleHash_NameSpaceTable_MatchEntry(PLDHashTable *table,
|
|||
NS_STATIC_CAST(const RuleHashTableEntry*, hdr);
|
||||
|
||||
return NS_PTR_TO_INT32(key) ==
|
||||
entry->mRules->mRule->FirstSelector()->mNameSpace;
|
||||
entry->mRules->mSelector->mNameSpace;
|
||||
}
|
||||
|
||||
static PLDHashTableOps RuleHash_TagTable_Ops = {
|
||||
|
@ -322,23 +336,26 @@ static PLDHashTableOps RuleHash_NameSpaceTable_Ops = {
|
|||
#endif
|
||||
|
||||
// Enumerator callback function.
|
||||
typedef void (*RuleEnumFunc)(nsICSSStyleRule* aRule, void *aData);
|
||||
typedef void (*RuleEnumFunc)(nsICSSStyleRule* aRule,
|
||||
nsCSSSelector* aSelector,
|
||||
void *aData);
|
||||
|
||||
class RuleHash {
|
||||
public:
|
||||
RuleHash(PRBool aQuirksMode);
|
||||
~RuleHash();
|
||||
void PrependRule(nsICSSStyleRule* aRule);
|
||||
void PrependRule(RuleValue *aRuleInfo);
|
||||
void EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID,
|
||||
const nsVoidArray& aClassList,
|
||||
RuleEnumFunc aFunc, void* aData);
|
||||
void EnumerateTagRules(nsIAtom* aTag,
|
||||
RuleEnumFunc aFunc, void* aData);
|
||||
PLArenaPool& Arena() { return mArena; }
|
||||
|
||||
protected:
|
||||
void PrependRuleToTable(PLDHashTable* aTable, const void* aKey,
|
||||
nsICSSStyleRule* aRule);
|
||||
void PrependUniversalRule(nsICSSStyleRule* aRule);
|
||||
RuleValue* aRuleInfo);
|
||||
void PrependUniversalRule(RuleValue* aRuleInfo);
|
||||
|
||||
// All rule values in these hashtables are arena allocated
|
||||
PRInt32 mRuleCount;
|
||||
|
@ -436,7 +453,11 @@ RuleHash::~RuleHash(void)
|
|||
do {
|
||||
nsAutoString selectorText;
|
||||
PRUint32 lineNumber = value->mRule->GetLineNumber();
|
||||
value->mRule->GetSourceSelectorText(selectorText);
|
||||
nsCOMPtr<nsIStyleSheet> sheet;
|
||||
value->mRule->GetStyleSheet(*getter_AddRefs(sheet));
|
||||
nsCOMPtr<nsICSSStyleSheet> cssSheet = do_QueryInterface(sheet);
|
||||
value->mSelector->ToString(selectorText, cssSheet);
|
||||
|
||||
printf(" line %d, %s\n",
|
||||
lineNumber, NS_ConvertUCS2toUTF8(selectorText).get());
|
||||
value = value->mNext;
|
||||
|
@ -459,45 +480,44 @@ RuleHash::~RuleHash(void)
|
|||
PL_FinishArenaPool(&mArena);
|
||||
}
|
||||
|
||||
void RuleHash::PrependRuleToTable(PLDHashTable* aTable,
|
||||
const void* aKey, nsICSSStyleRule* aRule)
|
||||
void RuleHash::PrependRuleToTable(PLDHashTable* aTable, const void* aKey,
|
||||
RuleValue* aRuleInfo)
|
||||
{
|
||||
// Get a new or existing entry.
|
||||
RuleHashTableEntry *entry = NS_STATIC_CAST(RuleHashTableEntry*,
|
||||
PL_DHashTableOperate(aTable, aKey, PL_DHASH_ADD));
|
||||
if (!entry)
|
||||
return;
|
||||
entry->mRules = new (mArena) RuleValue(aRule, mRuleCount++, entry->mRules);
|
||||
entry->mRules = aRuleInfo->Add(mRuleCount++, entry->mRules);
|
||||
}
|
||||
|
||||
void RuleHash::PrependUniversalRule(nsICSSStyleRule* aRule)
|
||||
void RuleHash::PrependUniversalRule(RuleValue *aRuleInfo)
|
||||
{
|
||||
mUniversalRules =
|
||||
new (mArena) RuleValue(aRule, mRuleCount++, mUniversalRules);
|
||||
mUniversalRules = aRuleInfo->Add(mRuleCount++, mUniversalRules);
|
||||
}
|
||||
|
||||
void RuleHash::PrependRule(nsICSSStyleRule* aRule)
|
||||
void RuleHash::PrependRule(RuleValue *aRuleInfo)
|
||||
{
|
||||
nsCSSSelector* selector = aRule->FirstSelector();
|
||||
nsCSSSelector *selector = aRuleInfo->mSelector;
|
||||
if (nsnull != selector->mIDList) {
|
||||
PrependRuleToTable(&mIdTable, selector->mIDList->mAtom, aRule);
|
||||
PrependRuleToTable(&mIdTable, selector->mIDList->mAtom, aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mIdSelectors);
|
||||
}
|
||||
else if (nsnull != selector->mClassList) {
|
||||
PrependRuleToTable(&mClassTable, selector->mClassList->mAtom, aRule);
|
||||
PrependRuleToTable(&mClassTable, selector->mClassList->mAtom, aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mClassSelectors);
|
||||
}
|
||||
else if (nsnull != selector->mTag) {
|
||||
PrependRuleToTable(&mTagTable, selector->mTag, aRule);
|
||||
PrependRuleToTable(&mTagTable, selector->mTag, aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mTagSelectors);
|
||||
}
|
||||
else if (kNameSpaceID_Unknown != selector->mNameSpace) {
|
||||
PrependRuleToTable(&mNameSpaceTable,
|
||||
NS_INT32_TO_PTR(selector->mNameSpace), aRule);
|
||||
NS_INT32_TO_PTR(selector->mNameSpace), aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mNameSpaceSelectors);
|
||||
}
|
||||
else { // universal tag selector
|
||||
PrependUniversalRule(aRule);
|
||||
PrependUniversalRule(aRuleInfo);
|
||||
RULE_HASH_STAT_INCREMENT(mUniversalSelectors);
|
||||
}
|
||||
}
|
||||
|
@ -593,15 +613,16 @@ void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
|
|||
highestRuleIndex = ruleIndex;
|
||||
}
|
||||
}
|
||||
(*aFunc)(mEnumList[valueIndex]->mRule, aData);
|
||||
RuleValue *next = mEnumList[valueIndex]->mNext;
|
||||
RuleValue *cur = mEnumList[valueIndex];
|
||||
(*aFunc)(cur->mRule, cur->mSelector, aData);
|
||||
RuleValue *next = cur->mNext;
|
||||
mEnumList[valueIndex] = next ? next : mEnumList[--valueCount];
|
||||
}
|
||||
|
||||
// Fast loop over single value.
|
||||
RuleValue* value = mEnumList[0];
|
||||
do {
|
||||
(*aFunc)(value->mRule, aData);
|
||||
(*aFunc)(value->mRule, value->mSelector, aData);
|
||||
value = value->mNext;
|
||||
} while (value);
|
||||
}
|
||||
|
@ -617,7 +638,7 @@ void RuleHash::EnumerateTagRules(nsIAtom* aTag, RuleEnumFunc aFunc, void* aData)
|
|||
RuleValue *tagValue = entry->mRules;
|
||||
do {
|
||||
RULE_HASH_STAT_INCREMENT(mPseudoTagCalls);
|
||||
(*aFunc)(tagValue->mRule, aData);
|
||||
(*aFunc)(tagValue->mRule, tagValue->mSelector, aData);
|
||||
tagValue = tagValue->mNext;
|
||||
} while (tagValue);
|
||||
}
|
||||
|
@ -656,23 +677,19 @@ static PLDHashTableOps AttributeSelectorOps = {
|
|||
|
||||
struct RuleCascadeData {
|
||||
RuleCascadeData(nsIAtom *aMedium, PRBool aQuirksMode)
|
||||
: mWeightedRules(nsnull),
|
||||
mRuleHash(aQuirksMode),
|
||||
: mRuleHash(aQuirksMode),
|
||||
mStateSelectors(),
|
||||
mMedium(aMedium),
|
||||
mNext(nsnull)
|
||||
{
|
||||
NS_NewISupportsArray(&mWeightedRules);
|
||||
PL_DHashTableInit(&mAttributeSelectors, &AttributeSelectorOps, nsnull,
|
||||
sizeof(AttributeSelectorEntry), 16);
|
||||
}
|
||||
|
||||
~RuleCascadeData(void)
|
||||
{
|
||||
NS_IF_RELEASE(mWeightedRules);
|
||||
PL_DHashTableFinish(&mAttributeSelectors);
|
||||
}
|
||||
nsISupportsArray* mWeightedRules;
|
||||
RuleHash mRuleHash;
|
||||
nsVoidArray mStateSelectors;
|
||||
PLDHashTable mAttributeSelectors; // nsIAtom* -> nsVoidArray*
|
||||
|
@ -3880,14 +3897,14 @@ static PRBool SelectorMatchesTree(RuleProcessorData &data,
|
|||
return PRBool(nsnull == selector); // matches if ran out of selectors
|
||||
}
|
||||
|
||||
static void ContentEnumFunc(nsICSSStyleRule* aRule, void* aData)
|
||||
static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
|
||||
void* aData)
|
||||
{
|
||||
ElementRuleProcessorData* data = (ElementRuleProcessorData*)aData;
|
||||
|
||||
nsCSSSelector* selector = aRule->FirstSelector();
|
||||
if (SelectorMatches(*data, selector, 0, nsnull, 0)) {
|
||||
selector = selector->mNext;
|
||||
if (SelectorMatchesTree(*data, selector)) {
|
||||
if (SelectorMatches(*data, aSelector, 0, nsnull, 0)) {
|
||||
nsCSSSelector *next = aSelector->mNext;
|
||||
if (!next || SelectorMatchesTree(*data, next)) {
|
||||
// for performance, require that every implementation of
|
||||
// nsICSSStyleRule return the same pointer for nsIStyleRule (why
|
||||
// would anything multiply inherit nsIStyleRule anyway?)
|
||||
|
@ -3923,19 +3940,18 @@ CSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void PseudoEnumFunc(nsICSSStyleRule* aRule, void* aData)
|
||||
static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
|
||||
void* aData)
|
||||
{
|
||||
PseudoRuleProcessorData* data = (PseudoRuleProcessorData*)aData;
|
||||
|
||||
nsCSSSelector* selector = aRule->FirstSelector();
|
||||
|
||||
NS_ASSERTION(selector->mTag == data->mPseudoTag, "RuleHash failure");
|
||||
NS_ASSERTION(aSelector->mTag == data->mPseudoTag, "RuleHash failure");
|
||||
PRBool matches = PR_TRUE;
|
||||
if (data->mComparator)
|
||||
data->mComparator->PseudoMatches(data->mPseudoTag, selector, &matches);
|
||||
data->mComparator->PseudoMatches(data->mPseudoTag, aSelector, &matches);
|
||||
|
||||
if (matches) {
|
||||
selector = selector->mNext;
|
||||
nsCSSSelector *selector = aSelector->mNext;
|
||||
|
||||
if (selector) { // test next selector specially
|
||||
if (PRUnichar('+') == selector->mOperator) {
|
||||
|
@ -4113,17 +4129,17 @@ PRBool IsStateSelector(nsCSSSelector& aSelector)
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool
|
||||
AddRule(nsISupports* aRule, void* aCascade)
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
AddRule(void* aRuleInfo, void* aCascade)
|
||||
{
|
||||
nsICSSStyleRule* rule = NS_STATIC_CAST(nsICSSStyleRule*, aRule);
|
||||
RuleValue* ruleInfo = NS_STATIC_CAST(RuleValue*, aRuleInfo);
|
||||
RuleCascadeData *cascade = NS_STATIC_CAST(RuleCascadeData*, aCascade);
|
||||
|
||||
// Build the rule hash.
|
||||
cascade->mRuleHash.PrependRule(rule);
|
||||
cascade->mRuleHash.PrependRule(ruleInfo);
|
||||
|
||||
nsVoidArray* stateArray = &cascade->mStateSelectors;
|
||||
for (nsCSSSelector* selector = rule->FirstSelector();
|
||||
for (nsCSSSelector* selector = ruleInfo->mSelector;
|
||||
selector; selector = selector->mNext) {
|
||||
// Build mStateSelectors.
|
||||
if (IsStateSelector(*selector))
|
||||
|
@ -4153,15 +4169,24 @@ AddRule(nsISupports* aRule, void* aCascade)
|
|||
return PR_TRUE;
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(PRIntn)
|
||||
RuleArraysDestroy(nsHashKey *aKey, void *aData, void *aClosure)
|
||||
{
|
||||
delete NS_STATIC_CAST(nsAutoVoidArray*, aData);
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
struct CascadeEnumData {
|
||||
CascadeEnumData(nsIAtom* aMedium)
|
||||
CascadeEnumData(nsIAtom* aMedium, PLArenaPool& aArena)
|
||||
: mMedium(aMedium),
|
||||
mRuleArrays(64)
|
||||
mRuleArrays(nsnull, nsnull, RuleArraysDestroy, nsnull, 64),
|
||||
mArena(aArena)
|
||||
{
|
||||
}
|
||||
|
||||
nsIAtom* mMedium;
|
||||
nsSupportsHashtable mRuleArrays; // of nsISupportsArray
|
||||
nsObjectHashtable mRuleArrays; // of nsAutoVoidArray
|
||||
PLArenaPool& mArena;
|
||||
};
|
||||
|
||||
static PRBool
|
||||
|
@ -4175,16 +4200,21 @@ InsertRuleByWeight(nsISupports* aRule, void* aData)
|
|||
if (nsICSSRule::STYLE_RULE == type) {
|
||||
nsICSSStyleRule* styleRule = (nsICSSStyleRule*)rule;
|
||||
|
||||
PRInt32 weight = styleRule->GetWeight();
|
||||
nsPRUint32Key key(weight);
|
||||
nsCOMPtr<nsISupportsArray> rules(dont_AddRef(
|
||||
NS_STATIC_CAST(nsISupportsArray*, data->mRuleArrays.Get(&key))));
|
||||
if (!rules) {
|
||||
NS_NewISupportsArray(getter_AddRefs(rules));
|
||||
if (!rules) return PR_FALSE; // out of memory
|
||||
data->mRuleArrays.Put(&key, rules);
|
||||
for (nsCSSSelectorList *sel = styleRule->Selector();
|
||||
sel; sel = sel->mNext) {
|
||||
PRInt32 weight = sel->mWeight;
|
||||
nsPRUint32Key key(weight);
|
||||
nsAutoVoidArray *rules =
|
||||
NS_STATIC_CAST(nsAutoVoidArray*, data->mRuleArrays.Get(&key));
|
||||
if (!rules) {
|
||||
rules = new nsAutoVoidArray();
|
||||
if (!rules) return PR_FALSE; // out of memory
|
||||
data->mRuleArrays.Put(&key, rules);
|
||||
}
|
||||
RuleValue *info =
|
||||
new (data->mArena) RuleValue(styleRule, sel->mSelectors);
|
||||
rules->AppendElement(info);
|
||||
}
|
||||
rules->AppendElement(styleRule);
|
||||
}
|
||||
else if (nsICSSRule::MEDIA_RULE == type) {
|
||||
nsICSSMediaRule* mediaRule = (nsICSSMediaRule*)rule;
|
||||
|
@ -4221,7 +4251,7 @@ CSSRuleProcessor::CascadeSheetRulesInto(nsISupports* aSheet, void* aData)
|
|||
|
||||
struct RuleArrayData {
|
||||
PRInt32 mWeight;
|
||||
nsISupportsArray* mRuleArray;
|
||||
nsVoidArray* mRuleArray;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(int) CompareArrayData(const void* aArg1, const void* aArg2,
|
||||
|
@ -4243,11 +4273,11 @@ struct FillArrayData {
|
|||
RuleArrayData* mArrayData;
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(PRBool) FillArray(nsHashKey* aKey, void* aData,
|
||||
void* aClosure)
|
||||
PR_STATIC_CALLBACK(PRBool)
|
||||
FillArray(nsHashKey* aKey, void* aData, void* aClosure)
|
||||
{
|
||||
nsPRUint32Key* key = NS_STATIC_CAST(nsPRUint32Key*, aKey);
|
||||
nsISupportsArray* weightArray = NS_STATIC_CAST(nsISupportsArray*, aData);
|
||||
nsVoidArray* weightArray = NS_STATIC_CAST(nsVoidArray*, aData);
|
||||
FillArrayData* data = NS_STATIC_CAST(FillArrayData*, aClosure);
|
||||
|
||||
RuleArrayData& ruleData = data->mArrayData[data->mIndex++];
|
||||
|
@ -4262,8 +4292,8 @@ PR_STATIC_CALLBACK(PRBool) FillArray(nsHashKey* aKey, void* aData,
|
|||
* puts them all in one big array which has a primary sort by weight
|
||||
* and secondary sort by order.
|
||||
*/
|
||||
static void PutRulesInList(nsSupportsHashtable* aRuleArrays,
|
||||
nsISupportsArray* aWeightedRules)
|
||||
static void PutRulesInList(nsObjectHashtable* aRuleArrays,
|
||||
nsVoidArray* aWeightedRules)
|
||||
{
|
||||
PRInt32 arrayCount = aRuleArrays->Count();
|
||||
RuleArrayData* arrayData = new RuleArrayData[arrayCount];
|
||||
|
@ -4272,7 +4302,7 @@ static void PutRulesInList(nsSupportsHashtable* aRuleArrays,
|
|||
NS_QuickSort(arrayData, arrayCount, sizeof(RuleArrayData),
|
||||
CompareArrayData, nsnull);
|
||||
for (PRInt32 i = 0; i < arrayCount; ++i)
|
||||
aWeightedRules->AppendElements(arrayData[i].mRuleArray);
|
||||
aWeightedRules->AppendElements(*arrayData[i].mRuleArray);
|
||||
|
||||
delete [] arrayData;
|
||||
}
|
||||
|
@ -4295,11 +4325,12 @@ CSSRuleProcessor::GetRuleCascade(nsIPresContext* aPresContext, nsIAtom* aMedium)
|
|||
cascade = new RuleCascadeData(aMedium,
|
||||
eCompatibility_NavQuirks == quirkMode);
|
||||
if (cascade) {
|
||||
CascadeEnumData data(aMedium);
|
||||
CascadeEnumData data(aMedium, cascade->mRuleHash.Arena());
|
||||
mSheets->EnumerateForwards(CascadeSheetRulesInto, &data);
|
||||
PutRulesInList(&data.mRuleArrays, cascade->mWeightedRules);
|
||||
nsVoidArray weightedRules;
|
||||
PutRulesInList(&data.mRuleArrays, &weightedRules);
|
||||
|
||||
if (!cascade->mWeightedRules->EnumerateBackwards(AddRule, cascade)) {
|
||||
if (!weightedRules.EnumerateBackwards(AddRule, cascade)) {
|
||||
delete cascade;
|
||||
cascade = nsnull;
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration* aDecl,
|
|||
NS_PRECONDITION(aDecl, "Null decl!");
|
||||
|
||||
nsCOMPtr<nsICSSStyleRule> cssRule;
|
||||
nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsCSSSelector());
|
||||
nsresult rv = NS_NewCSSStyleRule(getter_AddRefs(cssRule), nsnull);
|
||||
if (NS_FAILED(rv)) {
|
||||
if (!aDeclOwnedByRule) {
|
||||
aDecl->RuleAbort();
|
||||
|
@ -121,7 +121,6 @@ nsDOMCSSAttributeDeclaration::SetCSSDeclaration(nsCSSDeclaration* aDecl,
|
|||
}
|
||||
|
||||
cssRule->SetDeclaration(aDecl);
|
||||
cssRule->SetWeight(PR_INT32_MAX);
|
||||
return mContent->SetHTMLAttribute(nsHTMLAtoms::style,
|
||||
nsHTMLValue(cssRule),
|
||||
aNotify);
|
||||
|
|
|
@ -130,12 +130,14 @@ public:
|
|||
|
||||
PRInt32 CalcWeight(void) const;
|
||||
|
||||
nsresult ToString( nsAString& aString, nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsPseudoElem, PRInt8 aNegatedIndex ) const;
|
||||
void ToString(nsAString& aString, nsICSSStyleSheet* aSheet) const;
|
||||
|
||||
private:
|
||||
|
||||
void AppendNegationToString(nsAString& aString);
|
||||
void ToStringInternal(nsAString& aString, nsICSSStyleSheet* aSheet,
|
||||
PRBool aIsPseudoElem,
|
||||
PRIntn aNegatedIndex) const;
|
||||
|
||||
public:
|
||||
PRInt32 mNameSpace;
|
||||
|
@ -151,6 +153,38 @@ public:
|
|||
nsCSSSelector* mNext;
|
||||
};
|
||||
|
||||
/**
|
||||
* A selector list is the unit of selectors that each style rule has.
|
||||
* For example, "P B, H1 B { ... }" would be a selector list with two
|
||||
* items (where each |nsCSSSelectorList| object's |mSelectors| has
|
||||
* an |mNext| for the P or H1). We represent them as linked lists.
|
||||
*/
|
||||
struct nsCSSSelectorList {
|
||||
nsCSSSelectorList(void);
|
||||
~nsCSSSelectorList(void);
|
||||
|
||||
/**
|
||||
* Push a copy of |aSelector| on to the beginning of |mSelectors|,
|
||||
* setting its |mNext| to the current value of |mSelectors|.
|
||||
*
|
||||
* The caller is responsible for updating |mWeight|.
|
||||
*/
|
||||
void AddSelector(const nsCSSSelector& aSelector);
|
||||
|
||||
/**
|
||||
* Should be used only on the first in the list
|
||||
*/
|
||||
void ToString(nsAString& aResult, nsICSSStyleSheet* aSheet);
|
||||
|
||||
/**
|
||||
* Do a deep clone. Should be used only on the first in the list.
|
||||
*/
|
||||
nsCSSSelectorList* Clone();
|
||||
|
||||
nsCSSSelector* mSelectors;
|
||||
PRInt32 mWeight;
|
||||
nsCSSSelectorList* mNext;
|
||||
};
|
||||
|
||||
// IID for the nsICSSStyleRule interface {7c277af0-af19-11d1-8031-006008159b5a}
|
||||
#define NS_ICSS_STYLE_RULE_IID \
|
||||
|
@ -160,11 +194,8 @@ class nsICSSStyleRule : public nsICSSRule {
|
|||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICSS_STYLE_RULE_IID)
|
||||
|
||||
virtual nsCSSSelector* FirstSelector(void) = 0;
|
||||
virtual void AddSelector(const nsCSSSelector& aSelector) = 0;
|
||||
virtual void DeleteSelector(nsCSSSelector* aSelector) = 0;
|
||||
virtual void SetSourceSelectorText(const nsString& aSelectorText) = 0;
|
||||
virtual void GetSourceSelectorText(nsString& aSelectorText) const = 0;
|
||||
// null for style attribute
|
||||
virtual nsCSSSelectorList* Selector(void) = 0;
|
||||
|
||||
virtual PRUint32 GetLineNumber(void) const = 0;
|
||||
virtual void SetLineNumber(PRUint32 aLineNumber) = 0;
|
||||
|
@ -172,9 +203,6 @@ public:
|
|||
virtual nsCSSDeclaration* GetDeclaration(void) const = 0;
|
||||
virtual void SetDeclaration(nsCSSDeclaration* aDeclaration) = 0;
|
||||
|
||||
virtual PRInt32 GetWeight(void) const = 0;
|
||||
virtual void SetWeight(PRInt32 aWeight) = 0;
|
||||
|
||||
virtual already_AddRefed<nsIStyleRule> GetImportantRule(void) = 0;
|
||||
|
||||
// Hook for inspector.
|
||||
|
@ -183,6 +211,6 @@ public:
|
|||
|
||||
nsresult
|
||||
NS_NewCSSStyleRule(nsICSSStyleRule** aInstancePtrResult,
|
||||
const nsCSSSelector& aSelector);
|
||||
nsCSSSelectorList* aSelector);
|
||||
|
||||
#endif /* nsICSSStyleRule_h___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче