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:
dbaron%dbaron.org 2003-06-14 23:50:54 +00:00
Родитель c3600c1ce8
Коммит 47ed1de93c
18 изменённых файлов: 557 добавлений и 593 удалений

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

@ -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___ */