NSCSSRULEPROCESSOR.CPP       coverage:  94.29 %func     76.27 %block


     1) /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2) // vim:cindent:tabstop=2:expandtab:shiftwidth=2:
     3) /* ***** BEGIN LICENSE BLOCK *****
     4)  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
     5)  *
     6)  * The contents of this file are subject to the Mozilla Public License Version
     7)  * 1.1 (the "License"); you may not use this file except in compliance with
     8)  * the License. You may obtain a copy of the License at
     9)  * http://www.mozilla.org/MPL/
    10)  *
    11)  * Software distributed under the License is distributed on an "AS IS" basis,
    12)  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    13)  * for the specific language governing rights and limitations under the
    14)  * License.
    15)  *
    16)  * The Original Code is mozilla.org code.
    17)  *
    18)  * The Initial Developer of the Original Code is
    19)  * Netscape Communications Corporation.
    20)  * Portions created by the Initial Developer are Copyright (C) 1998
    21)  * the Initial Developer. All Rights Reserved.
    22)  *
    23)  * Contributor(s):
    24)  *   L. David Baron <dbaron@dbaron.org>
    25)  *   Daniel Glazman <glazman@netscape.com>
    26)  *   Ehsan Akhgari <ehsan.akhgari@gmail.com>
    27)  *   Rob Arnold <robarnold@mozilla.com>
    28)  *
    29)  * Alternatively, the contents of this file may be used under the terms of
    30)  * either of the GNU General Public License Version 2 or later (the "GPL"),
    31)  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    32)  * in which case the provisions of the GPL or the LGPL are applicable instead
    33)  * of those above. If you wish to allow use of your version of this file only
    34)  * under the terms of either the GPL or the LGPL, and not to allow others to
    35)  * use your version of this file under the terms of the MPL, indicate your
    36)  * decision by deleting the provisions above and replace them with the notice
    37)  * and other provisions required by the GPL or the LGPL. If you do not delete
    38)  * the provisions above, a recipient may use your version of this file under
    39)  * the terms of any one of the MPL, the GPL or the LGPL.
    40)  *
    41)  * ***** END LICENSE BLOCK ***** */
    42) 
    43) /*
    44)  * style rule processor for CSS style sheets, responsible for selector
    45)  * matching and cascading
    46)  */
    47) 
    48) #include "nsCSSRuleProcessor.h"
    49) 
    50) #define PL_ARENA_CONST_ALIGN_MASK 7
    51) #define NS_RULEHASH_ARENA_BLOCK_SIZE (256)
    52) #include "plarena.h"
    53) 
    54) #include "nsCRT.h"
    55) #include "nsIAtom.h"
    56) #include "pldhash.h"
    57) #include "nsHashtable.h"
    58) #include "nsICSSPseudoComparator.h"
    59) #include "nsCSSRuleProcessor.h"
    60) #include "nsICSSStyleRule.h"
    61) #include "nsICSSGroupRule.h"
    62) #include "nsIDocument.h"
    63) #include "nsPresContext.h"
    64) #include "nsIEventStateManager.h"
    65) #include "nsGkAtoms.h"
    66) #include "nsString.h"
    67) #include "nsUnicharUtils.h"
    68) #include "nsDOMError.h"
    69) #include "nsRuleWalker.h"
    70) #include "nsCSSPseudoClasses.h"
    71) #include "nsIContent.h"
    72) #include "nsCOMPtr.h"
    73) #include "nsHashKeys.h"
    74) #include "nsStyleUtil.h"
    75) #include "nsQuickSort.h"
    76) #include "nsAttrValue.h"
    77) #include "nsAttrName.h"
    78) #include "nsILookAndFeel.h"
    79) #include "nsWidgetsCID.h"
    80) #include "nsServiceManagerUtils.h"
    81) #include "nsTArray.h"
    82) #include "nsContentUtils.h"
    83) #include "nsIMediaList.h"
    84) #include "nsCSSRules.h"
    85) #include "nsIPrincipal.h"
    86) #include "nsStyleSet.h"
    87) 
    88) #define VISITED_PSEUDO_PREF "layout.css.visited_links_enabled"
    89) 
    90) static PRBool gSupportVisitedPseudo = PR_TRUE;
    91) 
    92) static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
    93) static nsTArray< nsCOMPtr<nsIAtom> >* sSystemMetrics = 0;
    94) 
    95) struct RuleValue {
    96)   /**
    97)    * |RuleValue|s are constructed before they become part of the
    98)    * |RuleHash|, to act as rule/selector pairs.  |Add| is called when
    99)    * they are added to the |RuleHash|, and can be considered the second
   100)    * half of the constructor.
   101)    *
   102)    * |RuleValue|s are added to the rule hash from highest weight/order
   103)    * to lowest (since this is the fast way to build a singly linked
   104)    * list), so the index used to remember the order is backwards.
   105)    */
   106)   RuleValue(nsICSSStyleRule* aRule, nsCSSSelector* aSelector)
          ^ 39,013 
   107)     : mRule(aRule), mSelector(aSelector) {}
   108) 
   109)   RuleValue* Add(PRInt32 aBackwardIndex, RuleValue *aNext)
                     ^ 39,013 
   110)   {
   111)     mBackwardIndex = aBackwardIndex;
   112)     mNext = aNext;
   113)     return this;
   114)   }
   115)     
   116)   // CAUTION: ~RuleValue will never get called as RuleValues are arena
   117)   // allocated and arena cleanup will take care of deleting memory.
   118)   // Add code to RuleHash::~RuleHash to get it to call the destructor
   119)   // if any more cleanup needs to happen.
   120)   ~RuleValue()
   121)   {
   122)     // Rule values are arena allocated. No need for any deletion.
   123)   }
   124) 
   125)   // Placement new to arena allocate the RuleValues
   126)   void *operator new(size_t aSize, PLArenaPool &aArena) CPP_THROW_NEW {
                ^ 39,013 
   127)     void *mem;
   128)     PL_ARENA_ALLOCATE(mem, &aArena, aSize);
            ^ 119,371 (5)
   129)     return mem;
            ^ 39,013 
   130)   }
   131) 
   132)   nsICSSStyleRule*  mRule;
   133)   nsCSSSelector*    mSelector; // which of |mRule|'s selectors
   134)   PRInt32           mBackwardIndex; // High index means low weight/order.
   135)   RuleValue*        mNext;
   136) };
   137) 
   138) // ------------------------------
   139) // Rule hash table
   140) //
   141) 
   142) // Uses any of the sets of ops below.
   143) struct RuleHashTableEntry : public PLDHashEntryHdr {
   144)   RuleValue *mRules; // linked list of |RuleValue|, null-terminated
   145) };
   146) 
   147) static PLDHashNumber
   148) RuleHash_CIHashKey(PLDHashTable *table, const void *key)
        ^ 159,120 
   149) {
   150)   nsIAtom *atom = const_cast<nsIAtom*>(static_cast<const nsIAtom*>(key));
   151) 
   152)   nsAutoString str;
   153)   atom->ToString(str);
          ^ 159,120 
   154)   ToUpperCase(str);
          ^ 159,120 
   155)   return HashString(str);
          ^ 477,360 (3)
   156) }
   157) 
   158) typedef nsIAtom*
   159) (* RuleHashGetKey) (PLDHashTable *table, const PLDHashEntryHdr *entry);
   160) 
   161) struct RuleHashTableOps {
   162)   PLDHashTableOps ops;
   163)   // Extra callback to avoid duplicating the matchEntry callback for
   164)   // each table.  (There used to be a getKey callback in
   165)   // PLDHashTableOps.)
   166)   RuleHashGetKey getKey;
   167) };
   168) 
   169) inline const RuleHashTableOps*
   170) ToLocalOps(const PLDHashTableOps *aOps)
        ^ 434,181 
   171) {
   172)   return (const RuleHashTableOps*)
   173)            (((const char*) aOps) - offsetof(RuleHashTableOps, ops));
   174) }
   175) 
   176) static PRBool
   177) RuleHash_CIMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
        ^ 26,678 
   178)                       const void *key)
   179) {
   180)   nsIAtom *match_atom = const_cast<nsIAtom*>(static_cast<const nsIAtom*>
   181)                                               (key));
   182)   // Use our extra |getKey| callback to avoid code duplication.
   183)   nsIAtom *entry_atom = ToLocalOps(table->ops)->getKey(table, hdr);
                              ^ 53,356 (2)
   184) 
   185)   // Check for case-sensitive match first.
   186)   if (match_atom == entry_atom)
   187)     return PR_TRUE;
            ^ 26,621 
   188) 
   189)   const char *match_str, *entry_str;
   190)   match_atom->GetUTF8String(&match_str);
          ^ 57 
   191)   entry_atom->GetUTF8String(&entry_str);
          ^ 57 
   192) 
   193)   return (nsCRT::strcasecmp(entry_str, match_str) == 0);
          ^ 114 (2)
   194) }
   195) 
   196) static PRBool
   197) RuleHash_CSMatchEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
        ^ 407,503 
   198)                       const void *key)
   199) {
   200)   nsIAtom *match_atom = const_cast<nsIAtom*>(static_cast<const nsIAtom*>
   201)                                               (key));
   202)   // Use our extra |getKey| callback to avoid code duplication.
   203)   nsIAtom *entry_atom = ToLocalOps(table->ops)->getKey(table, hdr);
                              ^ 815,006 (2)
   204) 
   205)   return match_atom == entry_atom;
   206) }
   207) 
   208) static nsIAtom*
   209) RuleHash_TagTable_GetKey(PLDHashTable *table, const PLDHashEntryHdr *hdr)
        ^ 401,547 
   210) {
   211)   const RuleHashTableEntry *entry =
   212)     static_cast<const RuleHashTableEntry*>(hdr);
   213)   return entry->mRules->mSelector->mTag;
          ^ 401,547 
   214) }
   215) 
   216) static nsIAtom*
   217) RuleHash_ClassTable_GetKey(PLDHashTable *table, const PLDHashEntryHdr *hdr)
        ^ 30,998 
   218) {
   219)   const RuleHashTableEntry *entry =
   220)     static_cast<const RuleHashTableEntry*>(hdr);
   221)   return entry->mRules->mSelector->mClassList->mAtom;
          ^ 30,998 
   222) }
   223) 
   224) static nsIAtom*
   225) RuleHash_IdTable_GetKey(PLDHashTable *table, const PLDHashEntryHdr *hdr)
        ^ 1,636 
   226) {
   227)   const RuleHashTableEntry *entry =
   228)     static_cast<const RuleHashTableEntry*>(hdr);
   229)   return entry->mRules->mSelector->mIDList->mAtom;
          ^ 1,636 
   230) }
   231) 
   232) static PLDHashNumber
   233) RuleHash_NameSpaceTable_HashKey(PLDHashTable *table, const void *key)
        ^ 135,425 
   234) {
   235)   return NS_PTR_TO_INT32(key);
   236) }
   237) 
   238) static PRBool
   239) RuleHash_NameSpaceTable_MatchEntry(PLDHashTable *table,
        ^ 52,898 
   240)                                    const PLDHashEntryHdr *hdr,
   241)                                    const void *key)
   242) {
   243)   const RuleHashTableEntry *entry =
   244)     static_cast<const RuleHashTableEntry*>(hdr);
   245) 
   246)   return NS_PTR_TO_INT32(key) ==
   247)          entry->mRules->mSelector->mNameSpace;
   248) }
   249) 
   250) static const RuleHashTableOps RuleHash_TagTable_Ops = {
   251)   {
   252)   PL_DHashAllocTable,
   253)   PL_DHashFreeTable,
   254)   PL_DHashVoidPtrKeyStub,
   255)   RuleHash_CSMatchEntry,
   256)   PL_DHashMoveEntryStub,
   257)   PL_DHashClearEntryStub,
   258)   PL_DHashFinalizeStub,
   259)   NULL
   260)   },
   261)   RuleHash_TagTable_GetKey
   262) };
   263) 
   264) // Case-sensitive ops.
   265) static const RuleHashTableOps RuleHash_ClassTable_CSOps = {
   266)   {
   267)   PL_DHashAllocTable,
   268)   PL_DHashFreeTable,
   269)   PL_DHashVoidPtrKeyStub,
   270)   RuleHash_CSMatchEntry,
   271)   PL_DHashMoveEntryStub,
   272)   PL_DHashClearEntryStub,
   273)   PL_DHashFinalizeStub,
   274)   NULL
   275)   },
   276)   RuleHash_ClassTable_GetKey
   277) };
   278) 
   279) // Case-insensitive ops.
   280) static const RuleHashTableOps RuleHash_ClassTable_CIOps = {
   281)   {
   282)   PL_DHashAllocTable,
   283)   PL_DHashFreeTable,
   284)   RuleHash_CIHashKey,
   285)   RuleHash_CIMatchEntry,
   286)   PL_DHashMoveEntryStub,
   287)   PL_DHashClearEntryStub,
   288)   PL_DHashFinalizeStub,
   289)   NULL
   290)   },
   291)   RuleHash_ClassTable_GetKey
   292) };
   293) 
   294) // Case-sensitive ops.
   295) static const RuleHashTableOps RuleHash_IdTable_CSOps = {
   296)   {
   297)   PL_DHashAllocTable,
   298)   PL_DHashFreeTable,
   299)   PL_DHashVoidPtrKeyStub,
   300)   RuleHash_CSMatchEntry,
   301)   PL_DHashMoveEntryStub,
   302)   PL_DHashClearEntryStub,
   303)   PL_DHashFinalizeStub,
   304)   NULL
   305)   },
   306)   RuleHash_IdTable_GetKey
   307) };
   308) 
   309) // Case-insensitive ops.
   310) static const RuleHashTableOps RuleHash_IdTable_CIOps = {
   311)   {
   312)   PL_DHashAllocTable,
   313)   PL_DHashFreeTable,
   314)   RuleHash_CIHashKey,
   315)   RuleHash_CIMatchEntry,
   316)   PL_DHashMoveEntryStub,
   317)   PL_DHashClearEntryStub,
   318)   PL_DHashFinalizeStub,
   319)   NULL
   320)   },
   321)   RuleHash_IdTable_GetKey
   322) };
   323) 
   324) static const PLDHashTableOps RuleHash_NameSpaceTable_Ops = {
   325)   PL_DHashAllocTable,
   326)   PL_DHashFreeTable,
   327)   RuleHash_NameSpaceTable_HashKey,
   328)   RuleHash_NameSpaceTable_MatchEntry,
   329)   PL_DHashMoveEntryStub,
   330)   PL_DHashClearEntryStub,
   331)   PL_DHashFinalizeStub,
   332)   NULL,
   333) };
   334) 
   335) #undef RULE_HASH_STATS
   336) #undef PRINT_UNIVERSAL_RULES
   337) 
   338) #ifdef RULE_HASH_STATS
   339) #define RULE_HASH_STAT_INCREMENT(var_) PR_BEGIN_MACRO ++(var_); PR_END_MACRO
   340) #else
   341) #define RULE_HASH_STAT_INCREMENT(var_) PR_BEGIN_MACRO PR_END_MACRO
   342) #endif
   343) 
   344) // Enumerator callback function.
   345) typedef void (*RuleEnumFunc)(nsICSSStyleRule* aRule,
   346)                              nsCSSSelector* aSelector,
   347)                              void *aData);
   348) 
   349) class RuleHash {
   350) public:
   351)   RuleHash(PRBool aQuirksMode);
   352)   ~RuleHash();
   353)   void PrependRule(RuleValue *aRuleInfo);
   354)   void EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID,
   355)                          const nsAttrValue* aClassList,
   356)                          RuleEnumFunc aFunc, void* aData);
   357)   void EnumerateTagRules(nsIAtom* aTag,
   358)                          RuleEnumFunc aFunc, void* aData);
   359)   PLArenaPool& Arena() { return mArena; }
                       ^ 122 
   360) 
   361) protected:
   362)   void PrependRuleToTable(PLDHashTable* aTable, const void* aKey,
   363)                           RuleValue* aRuleInfo);
   364)   void PrependUniversalRule(RuleValue* aRuleInfo);
   365) 
   366)   // All rule values in these hashtables are arena allocated
   367)   PRInt32     mRuleCount;
   368)   PLDHashTable mIdTable;
   369)   PLDHashTable mClassTable;
   370)   PLDHashTable mTagTable;
   371)   PLDHashTable mNameSpaceTable;
   372)   RuleValue *mUniversalRules;
   373) 
   374)   RuleValue** mEnumList;
   375)   PRInt32     mEnumListSize;
   376) 
   377)   PLArenaPool mArena;
   378) 
   379) #ifdef RULE_HASH_STATS
   380)   PRUint32    mUniversalSelectors;
   381)   PRUint32    mNameSpaceSelectors;
   382)   PRUint32    mTagSelectors;
   383)   PRUint32    mClassSelectors;
   384)   PRUint32    mIdSelectors;
   385) 
   386)   PRUint32    mElementsMatched;
   387)   PRUint32    mPseudosMatched;
   388) 
   389)   PRUint32    mElementUniversalCalls;
   390)   PRUint32    mElementNameSpaceCalls;
   391)   PRUint32    mElementTagCalls;
   392)   PRUint32    mElementClassCalls;
   393)   PRUint32    mElementIdCalls;
   394) 
   395)   PRUint32    mPseudoTagCalls;
   396) #endif // RULE_HASH_STATS
   397) };
   398) 
   399) RuleHash::RuleHash(PRBool aQuirksMode)
                  ^ 122 
   400)   : mRuleCount(0),
   401)     mUniversalRules(nsnull),
   402)     mEnumList(nsnull), mEnumListSize(0)
   403) #ifdef RULE_HASH_STATS
   404)     ,
   405)     mUniversalSelectors(0),
   406)     mNameSpaceSelectors(0),
   407)     mTagSelectors(0),
   408)     mClassSelectors(0),
   409)     mIdSelectors(0),
   410)     mElementsMatched(0),
   411)     mPseudosMatched(0),
   412)     mElementUniversalCalls(0),
   413)     mElementNameSpaceCalls(0),
   414)     mElementTagCalls(0),
   415)     mElementClassCalls(0),
   416)     mElementIdCalls(0),
   417)     mPseudoTagCalls(0)
   418) #endif
   419) {
   420)   // Initialize our arena
   421)   PL_INIT_ARENA_POOL(&mArena, "RuleHashArena", NS_RULEHASH_ARENA_BLOCK_SIZE);
   422) 
   423)   PL_DHashTableInit(&mTagTable, &RuleHash_TagTable_Ops.ops, nsnull,
          ^ 122 
   424)                     sizeof(RuleHashTableEntry), 64);
   425)   PL_DHashTableInit(&mIdTable,
          ^ 366 (4)
   426)                     aQuirksMode ? &RuleHash_IdTable_CIOps.ops
   427)                                 : &RuleHash_IdTable_CSOps.ops,
   428)                     nsnull, sizeof(RuleHashTableEntry), 16);
   429)   PL_DHashTableInit(&mClassTable,
          ^ 366 (4)
   430)                     aQuirksMode ? &RuleHash_ClassTable_CIOps.ops
   431)                                 : &RuleHash_ClassTable_CSOps.ops,
   432)                     nsnull, sizeof(RuleHashTableEntry), 16);
   433)   PL_DHashTableInit(&mNameSpaceTable, &RuleHash_NameSpaceTable_Ops, nsnull,
          ^ 122 
   434)                     sizeof(RuleHashTableEntry), 16);
   435) }
        ^ 122 
   436) 
   437) RuleHash::~RuleHash()
                  ^ 122 
   438) {
   439) #ifdef RULE_HASH_STATS
   440)   printf(
   441) "RuleHash(%p):\n"
   442) "  Selectors: Universal (%u) NameSpace(%u) Tag(%u) Class(%u) Id(%u)\n"
   443) "  Content Nodes: Elements(%u) Pseudo-Elements(%u)\n"
   444) "  Element Calls: Universal(%u) NameSpace(%u) Tag(%u) Class(%u) Id(%u)\n"
   445) "  Pseudo-Element Calls: Tag(%u)\n",
   446)          static_cast<void*>(this),
   447)          mUniversalSelectors, mNameSpaceSelectors, mTagSelectors,
   448)            mClassSelectors, mIdSelectors,
   449)          mElementsMatched,
   450)          mPseudosMatched,
   451)          mElementUniversalCalls, mElementNameSpaceCalls, mElementTagCalls,
   452)            mElementClassCalls, mElementIdCalls,
   453)          mPseudoTagCalls);
   454) #ifdef PRINT_UNIVERSAL_RULES
   455)   {
   456)     RuleValue* value = mUniversalRules;
   457)     if (value) {
   458)       printf("  Universal rules:\n");
   459)       do {
   460)         nsAutoString selectorText;
   461)         PRUint32 lineNumber = value->mRule->GetLineNumber();
   462)         nsCOMPtr<nsIStyleSheet> sheet;
   463)         value->mRule->GetStyleSheet(*getter_AddRefs(sheet));
   464)         nsCOMPtr<nsICSSStyleSheet> cssSheet = do_QueryInterface(sheet);
   465)         value->mSelector->ToString(selectorText, cssSheet);
   466) 
   467)         printf("    line %d, %s\n",
   468)                lineNumber, NS_ConvertUTF16toUTF8(selectorText).get());
   469)         value = value->mNext;
   470)       } while (value);
   471)     }
   472)   }
   473) #endif // PRINT_UNIVERSAL_RULES
   474) #endif // RULE_HASH_STATS
   475)   // Rule Values are arena allocated no need to delete them. Their destructor
   476)   // isn't doing any cleanup. So we dont even bother to enumerate through
   477)   // the hash tables and call their destructors.
   478)   if (nsnull != mEnumList) {
   479)     delete [] mEnumList;
            ^ 122 
   480)   }
   481)   // delete arena for strings and small objects
   482)   PL_DHashTableFinish(&mIdTable);
          ^ 122 
   483)   PL_DHashTableFinish(&mClassTable);
          ^ 122 
   484)   PL_DHashTableFinish(&mTagTable);
          ^ 122 
   485)   PL_DHashTableFinish(&mNameSpaceTable);
          ^ 122 
   486)   PL_FinishArenaPool(&mArena);
          ^ 122 
   487) }
        ^ 122 
   488) 
   489) void RuleHash::PrependRuleToTable(PLDHashTable* aTable, const void* aKey,
                       ^ 38,678 
   490)                                   RuleValue* aRuleInfo)
   491) {
   492)   // Get a new or existing entry.
   493)   RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                    ^ 38,678 
   494)                                          (PL_DHashTableOperate(aTable, aKey, PL_DHASH_ADD));
   495)   if (!entry)
   496)     return;
            ^ 0 
   497)   entry->mRules = aRuleInfo->Add(mRuleCount++, entry->mRules);
          ^ 77,356 (2)
   498) }
   499) 
   500) void RuleHash::PrependUniversalRule(RuleValue *aRuleInfo)
                       ^ 335 
   501) {
   502)   mUniversalRules = aRuleInfo->Add(mRuleCount++, mUniversalRules);
          ^ 335 
   503) }
   504) 
   505) void RuleHash::PrependRule(RuleValue *aRuleInfo)
                       ^ 39,013 
   506) {
   507)   nsCSSSelector *selector = aRuleInfo->mSelector;
   508)   if (nsnull != selector->mIDList) {
   509)     PrependRuleToTable(&mIdTable, selector->mIDList->mAtom, aRuleInfo);
            ^ 1,938 (2)
   510)     RULE_HASH_STAT_INCREMENT(mIdSelectors);
            ^ 969 
   511)   }
   512)   else if (nsnull != selector->mClassList) {
               ^ 38,044 
   513)     PrependRuleToTable(&mClassTable, selector->mClassList->mAtom, aRuleInfo);
            ^ 15,356 (2)
   514)     RULE_HASH_STAT_INCREMENT(mClassSelectors);
            ^ 7,678 
   515)   }
   516)   else if (nsnull != selector->mTag) {
               ^ 60,732 (2)
   517)     PrependRuleToTable(&mTagTable, selector->mTag, aRuleInfo);
            ^ 59,506 (2)
   518)     RULE_HASH_STAT_INCREMENT(mTagSelectors);
            ^ 29,753 
   519)   }
   520)   else if (kNameSpaceID_Unknown != selector->mNameSpace) {
               ^ 613 
   521)     PrependRuleToTable(&mNameSpaceTable,
            ^ 278 
   522)                        NS_INT32_TO_PTR(selector->mNameSpace), aRuleInfo);
   523)     RULE_HASH_STAT_INCREMENT(mNameSpaceSelectors);
            ^ 278 
   524)   }
   525)   else {  // universal tag selector
   526)     PrependUniversalRule(aRuleInfo);
            ^ 335 
   527)     RULE_HASH_STAT_INCREMENT(mUniversalSelectors);
            ^ 335 
   528)   }
   529) }
        ^ 39,013 
   530) 
   531) // this should cover practically all cases so we don't need to reallocate
   532) #define MIN_ENUM_LIST_SIZE 8
   533) 
   534) #ifdef RULE_HASH_STATS
   535) #define RULE_HASH_STAT_INCREMENT_LIST_COUNT(list_, var_) \
   536)   do { ++(var_); (list_) = (list_)->mNext; } while (list_)
   537) #else
   538) #define RULE_HASH_STAT_INCREMENT_LIST_COUNT(list_, var_) \
   539)   PR_BEGIN_MACRO PR_END_MACRO
   540) #endif
   541) 
   542) void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
                       ^ 135,147 
   543)                                  nsIAtom* aID, const nsAttrValue* aClassList,
   544)                                  RuleEnumFunc aFunc, void* aData)
   545) {
   546)   PRInt32 classCount = aClassList ? aClassList->GetAtomCount() : 0;
                             ^ 342,515 (4)
   547) 
   548)   // assume 1 universal, tag, id, and namespace, rather than wasting
   549)   // time counting
   550)   PRInt32 testCount = classCount + 4;
   551) 
   552)   if (mEnumListSize < testCount) {
   553)     delete [] mEnumList;
            ^ 132 
   554)     mEnumListSize = PR_MAX(testCount, MIN_ENUM_LIST_SIZE);
            ^ 132 
   555)     mEnumList = new RuleValue*[mEnumListSize];
            ^ 132 
   556)   }
   557) 
   558)   PRInt32 valueCount = 0;
                             ^ 135,147 
   559)   RULE_HASH_STAT_INCREMENT(mElementsMatched);
          ^ 135,147 
   560) 
   561)   { // universal rules
   562)     RuleValue* value = mUniversalRules;
                             ^ 135,147 
   563)     if (nsnull != value) {
   564)       mEnumList[valueCount++] = value;
              ^ 125,024 
   565)       RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementUniversalCalls);
              ^ 125,024 
   566)     }
   567)   }
   568)   // universal rules within the namespace
   569)   if (kNameSpaceID_Unknown != aNameSpace) {
          ^ 135,147 
   570)     RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                      ^ 270,294 (2)
   571)                                            (PL_DHashTableOperate(&mNameSpaceTable, NS_INT32_TO_PTR(aNameSpace),
   572)                              PL_DHASH_LOOKUP));
   573)     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
   574)       RuleValue *value = entry->mRules;
                               ^ 52,692 
   575)       mEnumList[valueCount++] = value;
   576)       RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementNameSpaceCalls);
              ^ 52,692 
   577)     }
   578)   }
   579)   if (nsnull != aTag) {
          ^ 135,147 
   580)     RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                      ^ 270,294 (2)
   581)                                            (PL_DHashTableOperate(&mTagTable, aTag, PL_DHASH_LOOKUP));
   582)     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
   583)       RuleValue *value = entry->mRules;
                               ^ 80,537 
   584)       mEnumList[valueCount++] = value;
   585)       RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementTagCalls);
              ^ 80,537 
   586)     }
   587)   }
   588)   if (nsnull != aID) {
          ^ 135,147 
   589)     RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                      ^ 109,456 (2)
   590)                                            (PL_DHashTableOperate(&mIdTable, aID, PL_DHASH_LOOKUP));
   591)     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
   592)       RuleValue *value = entry->mRules;
                               ^ 1,086 
   593)       mEnumList[valueCount++] = value;
   594)       RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementIdCalls);
              ^ 1,086 
   595)     }
   596)   }
   597)   { // extra scope to work around compiler bugs with |for| scoping.
   598)     for (PRInt32 index = 0; index < classCount; ++index) {
            ^ 246,820 (2)      ^ 135,147 
   599)       RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                        ^ 335,019 (3)
   600)                                              (PL_DHashTableOperate(&mClassTable, aClassList->AtomAt(index),
   601)                              PL_DHASH_LOOKUP));
   602)       if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
   603)         RuleValue *value = entry->mRules;
                                 ^ 29,276 
   604)         mEnumList[valueCount++] = value;
   605)         RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementClassCalls);
                ^ 29,276 
   606)       }
   607)     }
   608)   }
   609)   NS_ASSERTION(valueCount <= testCount, "values exceeded list size");
          ^ 135,147 
   610) 
   611)   if (valueCount > 0) {
          ^ 135,147 
   612)     // Merge the lists while there are still multiple lists to merge.
   613)     while (valueCount > 1) {
            ^ 2,288,339 (2)
   614)       PRInt32 valueIndex = 0;
                                 ^ 2,155,622 
   615)       PRInt32 highestRuleIndex = mEnumList[valueIndex]->mBackwardIndex;
   616)       for (PRInt32 index = 1; index < valueCount; ++index) {
              ^ 5,186,311 (2)
   617)         PRInt32 ruleIndex = mEnumList[index]->mBackwardIndex;
                                  ^ 3,030,689 
   618)         if (ruleIndex > highestRuleIndex) {
   619)           valueIndex = index;
                  ^ 1,920,683 
   620)           highestRuleIndex = ruleIndex;
   621)         }
   622)       }
   623)       RuleValue *cur = mEnumList[valueIndex];
                             ^ 2,155,622 
   624)       (*aFunc)(cur->mRule, cur->mSelector, aData);
   625)       RuleValue *next = cur->mNext;
                              ^ 2,155,622 
   626)       mEnumList[valueIndex] = next ? next : mEnumList[--valueCount];
              ^ 2,155,622 (2)
   627)     }
   628) 
   629)     // Fast loop over single value.
   630)     RuleValue* value = mEnumList[0];
                             ^ 132,717 
   631)     do {
   632)       (*aFunc)(value->mRule, value->mSelector, aData);
              ^ 428,513 
   633)       value = value->mNext;
              ^ 428,513 
   634)     } while (value);
   635)   }
   636) }
        ^ 135,147 
   637) 
   638) void RuleHash::EnumerateTagRules(nsIAtom* aTag, RuleEnumFunc aFunc, void* aData)
                       ^ 718,369 
   639) {
   640)   RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                    ^ 718,369 
   641)                                          (PL_DHashTableOperate(&mTagTable, aTag, PL_DHASH_LOOKUP));
   642) 
   643)   RULE_HASH_STAT_INCREMENT(mPseudosMatched);
          ^ 718,369 
   644)   if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
          ^ 718,369 
   645)     RuleValue *tagValue = entry->mRules;
                                ^ 300,615 
   646)     do {
   647)       RULE_HASH_STAT_INCREMENT(mPseudoTagCalls);
              ^ 1,292,423 
   648)       (*aFunc)(tagValue->mRule, tagValue->mSelector, aData);
              ^ 1,292,423 
   649)       tagValue = tagValue->mNext;
              ^ 1,292,423 
   650)     } while (tagValue);
   651)   }
   652) }
        ^ 718,369 
   653) 
   654) //--------------------------------
   655) 
   656) // Attribute selectors hash table.
   657) struct AttributeSelectorEntry : public PLDHashEntryHdr {
   658)   nsIAtom *mAttribute;
   659)   nsTArray<nsCSSSelector*> *mSelectors;
   660) };
   661) 
   662) static void
   663) AttributeSelectorClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
        ^ 1,596 
   664) {
   665)   AttributeSelectorEntry *entry = static_cast<AttributeSelectorEntry*>(hdr);
   666)   delete entry->mSelectors;
          ^ 1,596 
   667)   memset(entry, 0, table->entrySize);
          ^ 1,596 
   668) }
        ^ 1,596 
   669) 
   670) static const PLDHashTableOps AttributeSelectorOps = {
   671)   PL_DHashAllocTable,
   672)   PL_DHashFreeTable,
   673)   PL_DHashVoidPtrKeyStub,
   674)   PL_DHashMatchEntryStub,
   675)   PL_DHashMoveEntryStub,
   676)   AttributeSelectorClearEntry,
   677)   PL_DHashFinalizeStub,
   678)   NULL
   679) };
   680) 
   681) 
   682) //--------------------------------
   683) 
   684) struct RuleCascadeData {
   685)   RuleCascadeData(nsIAtom *aMedium, PRBool aQuirksMode)
          ^ 854 (7)
   686)     : mRuleHash(aQuirksMode),
   687)       mStateSelectors(),
   688)       mCacheKey(aMedium),
   689)       mNext(nsnull)
   690)   {
   691)     PL_DHashTableInit(&mAttributeSelectors, &AttributeSelectorOps, nsnull,
   692)                       sizeof(AttributeSelectorEntry), 16);
   693)   }
          ^ 122 
   694) 
   695)   ~RuleCascadeData()
          ^ 122 
   696)   {
   697)     PL_DHashTableFinish(&mAttributeSelectors);
   698)   }
          ^ 854 (7)
   699)   RuleHash                 mRuleHash;
   700)   nsTArray<nsCSSSelector*> mStateSelectors;
   701)   nsTArray<nsCSSSelector*> mClassSelectors;
   702)   nsTArray<nsCSSSelector*> mIDSelectors;
   703)   PLDHashTable             mAttributeSelectors;
   704) 
   705)   nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
   706) 
   707)   // Looks up or creates the appropriate list in |mAttributeSelectors|.
   708)   // Returns null only on allocation failure.
   709)   nsTArray<nsCSSSelector*>* AttributeListFor(nsIAtom* aAttribute);
   710) 
   711)   nsMediaQueryResultCacheKey mCacheKey;
   712)   RuleCascadeData*  mNext; // for a different medium
   713) };
   714) 
   715) nsTArray<nsCSSSelector*>*
   716) RuleCascadeData::AttributeListFor(nsIAtom* aAttribute)
                         ^ 8,866 
   717) {
   718)   AttributeSelectorEntry *entry = static_cast<AttributeSelectorEntry*>
                                        ^ 8,866 
   719)                                              (PL_DHashTableOperate(&mAttributeSelectors, aAttribute, PL_DHASH_ADD));
   720)   if (!entry)
   721)     return nsnull;
            ^ 0 
   722)   if (!entry->mSelectors) {
          ^ 8,866 
   723)     if (!(entry->mSelectors = new nsTArray<nsCSSSelector*>)) {
            ^ 7,980 (5/6)
   724)       PL_DHashTableRawRemove(&mAttributeSelectors, entry);
              ^ 0 
   725)       return nsnull;
              ^ 0 
   726)     }
   727)     entry->mAttribute = aAttribute;
            ^ 1,596 
   728)   }
   729)   return entry->mSelectors;
          ^ 8,866 
   730) }
   731) 
   732) // -------------------------------
   733) // CSS Style rule processor implementation
   734) //
   735) 
   736) nsCSSRuleProcessor::nsCSSRuleProcessor(const nsCOMArray<nsICSSStyleSheet>& aSheets,
                            ^ 644 (4)
   737)                                        PRUint8 aSheetType)
   738)   : mSheets(aSheets)
   739)   , mRuleCascades(nsnull)
   740)   , mLastPresContext(nsnull)
   741)   , mSheetType(aSheetType)
   742) {
   743)   for (PRInt32 i = mSheets.Count() - 1; i >= 0; --i)
          ^ 551 (2)      ^ 161 
   744)     mSheets[i]->AddRuleProcessor(this);
            ^ 780 (2)
   745) }
        ^ 161 
   746) 
   747) nsCSSRuleProcessor::~nsCSSRuleProcessor()
                            ^ 161 
   748) {
   749)   for (PRInt32 i = mSheets.Count() - 1; i >= 0; --i)
          ^ 551 (2)      ^ 161 
   750)     mSheets[i]->DropRuleProcessor(this);
            ^ 780 (2)
   751)   mSheets.Clear();
          ^ 161 
   752)   ClearRuleCascades();
          ^ 161 
   753) }
        ^ 322 (2)
   754) 
   755) NS_IMPL_ISUPPORTS1(nsCSSRuleProcessor, nsIStyleRuleProcessor)
        ^ 2,415 (16/18)
   756) 
   757) /* static */ void
   758) nsCSSRuleProcessor::Startup()
   759) {
        ^ 1 
   760)   nsContentUtils::AddBoolPrefVarCache(VISITED_PSEUDO_PREF,
   761)                                       &gSupportVisitedPseudo);
   762)   // We want to default to true, not false as AddBoolPrefVarCache does.
   763)   gSupportVisitedPseudo =
          ^ 2 (2)
   764)     nsContentUtils::GetBoolPref(VISITED_PSEUDO_PREF, PR_TRUE);
   765) }
   766) 
   767) static PRBool
   768) InitSystemMetrics()
        ^ 1 
   769) {
   770)   NS_ASSERTION(!sSystemMetrics, "already initialized");
          ^ 1 
   771) 
   772)   sSystemMetrics = new nsTArray< nsCOMPtr<nsIAtom> >;
          ^ 5 (5/6)
   773)   NS_ENSURE_TRUE(sSystemMetrics, PR_FALSE);
          ^ 2 (2/4)
   774) 
   775)   nsresult rv;
   776)   nsCOMPtr<nsILookAndFeel> lookAndFeel(do_GetService(kLookAndFeelCID, &rv));
                                   ^ 2 (2)
   777)   NS_ENSURE_SUCCESS(rv, PR_FALSE);
          ^ 2 (2/5)
   778) 
   779)   PRInt32 metricResult;
   780)   lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ScrollArrowStyle, metricResult);
          ^ 2 (2)
   781)   if (metricResult & nsILookAndFeel::eMetric_ScrollArrowStartBackward) {
          ^ 1 
   782)     sSystemMetrics->AppendElement(do_GetAtom("scrollbar-start-backward"));
            ^ 2 (2)
   783)   }
   784)   if (metricResult & nsILookAndFeel::eMetric_ScrollArrowStartForward) {
          ^ 1 
   785)     sSystemMetrics->AppendElement(do_GetAtom("scrollbar-start-forward"));
            ^ 0 (2)
   786)   }
   787)   if (metricResult & nsILookAndFeel::eMetric_ScrollArrowEndBackward) {
          ^ 1 
   788)     sSystemMetrics->AppendElement(do_GetAtom("scrollbar-end-backward"));
            ^ 0 (2)
   789)   }
   790)   if (metricResult & nsILookAndFeel::eMetric_ScrollArrowEndForward) {
          ^ 1 
   791)     sSystemMetrics->AppendElement(do_GetAtom("scrollbar-end-forward"));
            ^ 2 (2)
   792)   }
   793) 
   794)   lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ScrollSliderStyle, metricResult);
          ^ 2 (2)
   795)   if (metricResult != nsILookAndFeel::eMetric_ScrollThumbStyleNormal) {
          ^ 1 
   796)     sSystemMetrics->AppendElement(do_GetAtom("scrollbar-thumb-proportional"));
            ^ 2 (2)
   797)   }
   798) 
   799)   lookAndFeel->GetMetric(nsILookAndFeel::eMetric_ImagesInMenus, metricResult);
          ^ 2 (2)
   800)   if (metricResult) {
          ^ 1 
   801)     sSystemMetrics->AppendElement(do_GetAtom("images-in-menus"));
            ^ 0 (2)
   802)   }
   803) 
   804)   rv = lookAndFeel->GetMetric(nsILookAndFeel::eMetric_WindowsDefaultTheme, metricResult);
          ^ 3 (3)
   805)   if (NS_SUCCEEDED(rv) && metricResult) {
          ^ 1 
   806)     sSystemMetrics->AppendElement(do_GetAtom("windows-default-theme"));
            ^ 2 (2)
   807)   }
   808) 
   809)   rv = lookAndFeel->GetMetric(nsILookAndFeel::eMetric_MacGraphiteTheme, metricResult);
          ^ 3 (3)
   810)   if (NS_SUCCEEDED(rv) && metricResult) {
          ^ 0 
   811)     sSystemMetrics->AppendElement(do_GetAtom("mac-graphite-theme"));
            ^ 0 (2)
   812)   }
   813) 
   814)   rv = lookAndFeel->GetMetric(nsILookAndFeel::eMetric_DWMCompositor, metricResult);
          ^ 3 (3)
   815)   if (NS_SUCCEEDED(rv) && metricResult) {
          ^ 1 
   816)     sSystemMetrics->AppendElement(do_GetAtom("windows-compositor"));
            ^ 0 (2)
   817)   }
   818) 
   819)   rv = lookAndFeel->GetMetric(nsILookAndFeel::eMetric_WindowsClassic, metricResult);
          ^ 3 (3)
   820)   if (NS_SUCCEEDED(rv) && metricResult) {
          ^ 1 
   821)     sSystemMetrics->AppendElement(do_GetAtom("windows-classic"));
            ^ 0 (2)
   822)   }
   823)  
   824)   return PR_TRUE;
          ^ 2 (2)
   825) }
   826) 
   827) /* static */ void
   828) nsCSSRuleProcessor::FreeSystemMetrics()
   829) {
        ^ 1 
   830)   delete sSystemMetrics;
          ^ 1 
   831)   sSystemMetrics = nsnull;
          ^ 1 
   832) }
   833) 
   834) RuleProcessorData::RuleProcessorData(nsPresContext* aPresContext,
                           ^ 916,140 
   835)                                      nsIContent* aContent, 
   836)                                      nsRuleWalker* aRuleWalker,
   837)                                      nsCompatibility* aCompat /*= nsnull*/)
   838) {
   839)   MOZ_COUNT_CTOR(RuleProcessorData);
   840) 
   841)   NS_ASSERTION(!aContent || aContent->IsNodeOfType(nsINode::eELEMENT),
          ^ 916,140 
   842)                "non-element leaked into SelectorMatches");
   843) 
   844)   mPresContext = aPresContext;
          ^ 916,140 
   845)   mContent = aContent;
   846)   mParentContent = nsnull;
   847)   mRuleWalker = aRuleWalker;
   848)   mScopedRoot = nsnull;
   849) 
   850)   mContentTag = nsnull;
   851)   mContentID = nsnull;
   852)   mHasAttributes = PR_FALSE;
   853)   mIsHTMLContent = PR_FALSE;
   854)   mIsLink = PR_FALSE;
   855)   mLinkState = eLinkState_Unknown;
   856)   mEventState = 0;
   857)   mNameSpaceID = kNameSpaceID_Unknown;
   858)   mPreviousSiblingData = nsnull;
   859)   mParentData = nsnull;
   860)   mLanguage = nsnull;
   861)   mClasses = nsnull;
   862)   mNthIndices[0][0] = -2;
   863)   mNthIndices[0][1] = -2;
   864)   mNthIndices[1][0] = -2;
   865)   mNthIndices[1][1] = -2;
   866) 
   867)   // get the compat. mode (unless it is provided)
   868)   // XXXbz is passing in the compat mode really that much of an optimization?
   869)   if (aCompat) {
   870)     mCompatMode = *aCompat;
            ^ 597,313 
   871)   } else if (NS_LIKELY(mPresContext)) {
                 ^ 318,827 
   872)     mCompatMode = mPresContext->CompatibilityMode();
            ^ 637,654 (2)
   873)   } else {
   874)     NS_ASSERTION(aContent, "Must have content");
            ^ 0 
   875)     NS_ASSERTION(aContent->GetOwnerDoc(), "Must have document");
            ^ 0 
   876)     mCompatMode = aContent->GetOwnerDoc()->GetCompatibilityMode();
            ^ 0 (3)
   877)   }
   878) 
   879)   if (aContent) {
          ^ 916,140 
   880)     NS_ASSERTION(aContent->GetOwnerDoc(), "Document-less node here?");
            ^ 916,069 
   881)     
   882)     // get the tag and parent
   883)     mContentTag = aContent->Tag();
            ^ 1,832,138 (2)
   884)     mParentContent = aContent->GetParent();
            ^ 916,069 
   885) 
   886)     // get the event state
   887)     if (mPresContext) {
   888)       mPresContext->EventStateManager()->GetContentState(aContent, mEventState);
              ^ 1,832,138 (2)
   889)     } else {
   890)       mEventState = aContent->IntrinsicState();
              ^ 0 (2)
   891)     }
   892) 
   893)     // get the ID and classes for the content
   894)     mContentID = aContent->GetID();
            ^ 1,832,138 (2)
   895)     mClasses = aContent->GetClasses();
            ^ 916,069 
   896) 
   897)     // see if there are attributes for the content
   898)     mHasAttributes = aContent->GetAttrCount() > 0;
            ^ 916,069 
   899) 
   900)     // check for HTMLContent and Link status
   901)     if (aContent->IsNodeOfType(nsINode::eHTML)) {
            ^ 916,069 
   902)       mIsHTMLContent = PR_TRUE;
              ^ 860,276 
   903)       // Note that we want to treat non-XML HTML content as XHTML for namespace
   904)       // purposes, since html.css has that namespace declared.
   905)       mNameSpaceID = kNameSpaceID_XHTML;
   906)     } else {
   907)       // get the namespace
   908)       mNameSpaceID = aContent->GetNameSpaceID();
              ^ 111,586 (2)
   909)     }
   910) 
   911)     // if HTML content and it has some attributes, check for an HTML link
   912)     // NOTE: optimization: cannot be a link if no attributes (since it needs an href)
   913)     nsILinkHandler* linkHandler =
                                        ^ 3,664,276 (4/5)
   914)       mPresContext ? mPresContext->GetLinkHandler() : nsnull;
   915)     if (mIsHTMLContent && mHasAttributes) {
            ^ 860,276 
   916)       // check if it is an HTML Link
   917)       if(nsStyleUtil::IsHTMLLink(aContent, mContentTag, linkHandler,
              ^ 1,226,974 (2)
   918)                                  &mLinkState)) {
   919)         mIsLink = PR_TRUE;
                ^ 604 
   920)       }
   921)     } 
   922) 
   923)     // if not an HTML link, check for a simple xlink (cannot be both HTML link and xlink)
   924)     // NOTE: optimization: cannot be an XLink if no attributes (since it needs an 
   925)     if(!mIsLink &&
            ^ 3,941,288 (8/11)
   926)        mHasAttributes && 
   927)        !(mIsHTMLContent || aContent->IsNodeOfType(nsINode::eXUL)) && 
   928)        nsStyleUtil::IsLink(aContent, linkHandler, &mLinkState)) {
   929)       mIsLink = PR_TRUE;
              ^ 0 
   930)     } 
   931)   }
   932) 
   933)   if (mLinkState == eLinkState_Visited && !gSupportVisitedPseudo) {
          ^ 916,148 (2)
   934)     mLinkState = eLinkState_Unvisited;
            ^ 0 
   935)   }
   936) }
        ^ 916,140 
   937) 
   938) RuleProcessorData::~RuleProcessorData()
                           ^ 916,140 
   939) {
   940)   MOZ_COUNT_DTOR(RuleProcessorData);
   941) 
   942)   // Destroy potentially long chains of previous sibling and parent data
   943)   // without more than one level of recursion.
   944)   if (mPreviousSiblingData || mParentData) {
          ^ 916,116 
   945)     nsAutoVoidArray destroyQueue;
                            ^ 55,442 
   946)     destroyQueue.AppendElement(this);
            ^ 55,442 
   947) 
   948)     do {
   949)       RuleProcessorData *d = static_cast<RuleProcessorData*>
                                   ^ 1,958,265 (3)
   950)                                         (destroyQueue.FastElementAt(destroyQueue.Count() - 1));
   951)       destroyQueue.RemoveElementAt(destroyQueue.Count() - 1);
              ^ 652,755 
   952) 
   953)       if (d->mPreviousSiblingData) {
              ^ 652,755 
   954)         destroyQueue.AppendElement(d->mPreviousSiblingData);
                ^ 55 
   955)         d->mPreviousSiblingData = nsnull;
                ^ 55 
   956)       }
   957)       if (d->mParentData) {
              ^ 652,755 
   958)         destroyQueue.AppendElement(d->mParentData);
                ^ 597,258 
   959)         d->mParentData = nsnull;
                ^ 597,258 
   960)       }
   961) 
   962)       if (d != this)
              ^ 652,755 
   963)         d->Destroy();
                ^ 597,313 
   964)     } while (destroyQueue.Count());
            ^ 1,305,510 (2)
   965)   }
          ^ 55,442 
   966) 
   967)   delete mLanguage;
          ^ 916,140 (1/2)
   968) }
        ^ 916,140 
   969) 
   970) const nsString* RuleProcessorData::GetLang()
        ^ 0 
   971) {
   972)   if (!mLanguage) {
   973)     mLanguage = new nsString();
   974)     if (!mLanguage)
   975)       return nsnull;
   976)     for (nsIContent* content = mContent; content;
   977)          content = content->GetParent()) {
   978)       if (content->GetAttrCount() > 0) {
   979)         // xml:lang has precedence over lang on HTML elements (see
   980)         // XHTML1 section C.7).
   981)         PRBool hasAttr = content->GetAttr(kNameSpaceID_XML, nsGkAtoms::lang,
   982)                                           *mLanguage);
   983)         if (!hasAttr && content->IsNodeOfType(nsINode::eHTML)) {
   984)           hasAttr = content->GetAttr(kNameSpaceID_None, nsGkAtoms::lang,
   985)                                      *mLanguage);
   986)         }
   987)         NS_ASSERTION(hasAttr || mLanguage->IsEmpty(),
   988)                      "GetAttr that returns false should not make string non-empty");
   989)         if (hasAttr) {
   990)           break;
   991)         }
   992)       }
   993)     }
   994)   }
   995)   return mLanguage;
   996) }
   997) 
   998) static inline PRInt32
   999) CSSNameSpaceID(nsIContent *aContent)
        ^ 0 
  1000) {
  1001)   return aContent->IsNodeOfType(nsINode::eHTML)
  1002)            ? kNameSpaceID_XHTML
  1003)            : aContent->GetNameSpaceID();
  1004) }
  1005) 
  1006) PRInt32
  1007) RuleProcessorData::GetNthIndex(PRBool aIsOfType, PRBool aIsFromEnd,
                           ^ 352 
  1008)                                PRBool aCheckEdgeOnly)
  1009) {
  1010)   NS_ASSERTION(mParentContent, "caller should check mParentContent");
          ^ 352 
  1011)   NS_ASSERTION(!mPreviousSiblingData ||
          ^ 352 
  1012)                mPreviousSiblingData->mContent->IsNodeOfType(nsINode::eELEMENT),
  1013)                "Unexpected previous sibling data");
  1014) 
  1015)   PRInt32 &slot = mNthIndices[aIsOfType][aIsFromEnd];
                        ^ 352 
  1016)   if (slot != -2 && (slot != -1 || aCheckEdgeOnly))
          ^ 128 (1/2)
  1017)     return slot;
            ^ 128 
  1018) 
  1019)   if (mPreviousSiblingData &&
          ^ 224 (1/4)
  1020)       (!aIsOfType ||
  1021)        (mPreviousSiblingData->mNameSpaceID == mNameSpaceID &&
  1022)         mPreviousSiblingData->mContentTag == mContentTag))) {
  1023)     slot = mPreviousSiblingData->mNthIndices[aIsOfType][aIsFromEnd];
            ^ 0 
  1024)     if (slot > 0) {
  1025)       slot += (aIsFromEnd ? -1 : 1);
              ^ 0 (4)
  1026)       NS_ASSERTION(slot > 0, "How did that happen?");
              ^ 0 
  1027)       return slot;
              ^ 0 
  1028)     }
  1029)   }
  1030) 
  1031)   PRInt32 result = 1;
                         ^ 224 
  1032)   nsIContent* parent = mParentContent;
  1033) 
  1034)   PRUint32 childCount;
  1035)   nsIContent * const * curChildPtr = parent->GetChildArray(&childCount);
                                           ^ 224 
  1036) 
  1037) #ifdef DEBUG
  1038)   nsMutationGuard debugMutationGuard;
  1039) #endif  
  1040)   
  1041)   PRInt32 increment;
  1042)   nsIContent * const * stopPtr;
  1043)   if (aIsFromEnd) {
  1044)     stopPtr = curChildPtr - 1;
            ^ 64 
  1045)     curChildPtr = stopPtr + childCount;
  1046)     increment = -1;
  1047)   } else {
  1048)     increment = 1;
            ^ 160 
  1049)     stopPtr = curChildPtr + childCount;
  1050)   }
  1051) 
  1052)   for ( ; ; curChildPtr += increment) {
          ^ 224 (1/2)
  1053)     if (curChildPtr == stopPtr) {
            ^ 224 
  1054)       // mContent is the root of an anonymous content subtree.
  1055)       result = 0; // special value to indicate that it is not at any index
              ^ 0 
  1056)       break;
  1057)     }
  1058)     nsIContent* child = *curChildPtr;
                              ^ 224 
  1059)     if (child == mContent)
  1060)       break;
  1061)     if (child->IsNodeOfType(nsINode::eELEMENT) &&
            ^ 72 (3/7)
  1062)         (!aIsOfType ||
  1063)          (child->Tag() == mContentTag &&
  1064)           CSSNameSpaceID(child) == mNameSpaceID))) {
  1065)       if (aCheckEdgeOnly) {
              ^ 24 
  1066)         // The caller only cares whether or not the result is 1, and we
  1067)         // now know it's not.
  1068)         result = -1;
                ^ 24 
  1069)         break;
  1070)       }
  1071)       ++result;
              ^ 0 
  1072)     }
  1073)   }
  1074) 
  1075) #ifdef DEBUG
  1076)   NS_ASSERTION(!debugMutationGuard.Mutated(0), "Unexpected mutations happened");
  1077) #endif  
  1078) 
  1079)   slot = result;
          ^ 224 
  1080)   return result;
  1081) }
  1082) 
  1083) static PRBool ValueIncludes(const nsSubstring& aValueList,
                      ^ 293 
  1084)                             const nsSubstring& aValue,
  1085)                             const nsStringComparator& aComparator)
  1086) {
  1087)   const PRUnichar *p = aValueList.BeginReading(),
                             ^ 293 
  1088)               *p_end = aValueList.EndReading();
                             ^ 293 
  1089) 
  1090)   while (p < p_end) {
          ^ 488 (2)
  1091)     // skip leading space
  1092)     while (p != p_end && nsContentUtils::IsHTMLWhitespace(*p))
            ^ 774 (3/4)
  1093)       ++p;
  1094) 
  1095)     const PRUnichar *val_start = p;
                                       ^ 258 
  1096) 
  1097)     // look for space or end
  1098)     while (p != p_end && !nsContentUtils::IsHTMLWhitespace(*p))
            ^ 7,224 (4)
  1099)       ++p;
  1100) 
  1101)     const PRUnichar *val_end = p;
                                     ^ 258 
  1102) 
  1103)     if (val_start < val_end &&
            ^ 1,806 (8/9)
  1104)         aValue.Equals(Substring(val_start, val_end), aComparator))
  1105)       return PR_TRUE;
              ^ 63 
  1106) 
  1107)     ++p; // we know the next character is not whitespace
  1108)   }
  1109)   return PR_FALSE;
          ^ 230 
  1110) }
  1111) 
  1112) inline PRBool IsLinkPseudo(nsIAtom* aAtom)
                      ^ 268,972 
  1113) {
  1114)   return PRBool ((nsCSSPseudoClasses::link == aAtom) || 
          ^ 941,834 (5)
  1115)                  (nsCSSPseudoClasses::visited == aAtom) ||
  1116)                  (nsCSSPseudoClasses::mozAnyLink == aAtom));
  1117) }
  1118) 
  1119) // Return whether we should apply a "global" (i.e., universal-tag)
  1120) // selector for event states in quirks mode.  Note that
  1121) // |data.mIsLink| is checked separately by the caller, so we return
  1122) // false for |nsGkAtoms::a|, which here means a named anchor.
  1123) inline PRBool IsQuirkEventSensitive(nsIAtom *aContentTag)
                      ^ 10,054 
  1124) {
  1125)   return PRBool ((nsGkAtoms::button == aContentTag) ||
          ^ 67,734 (8)
  1126)                  (nsGkAtoms::img == aContentTag)    ||
  1127)                  (nsGkAtoms::input == aContentTag)  ||
  1128)                  (nsGkAtoms::label == aContentTag)  ||
  1129)                  (nsGkAtoms::select == aContentTag) ||
  1130)                  (nsGkAtoms::textarea == aContentTag));
  1131) }
  1132) 
  1133) 
  1134) static inline PRBool
  1135) IsSignificantChild(nsIContent* aChild, PRBool aTextIsSignificant,
        ^ 620 
  1136)                    PRBool aWhitespaceIsSignificant)
  1137) {
  1138)   return nsStyleUtil::IsSignificantChild(aChild, aTextIsSignificant,
          ^ 620 
  1139)                                          aWhitespaceIsSignificant);
  1140) }
  1141) 
  1142) // This function is to be called once we have fetched a value for an attribute
  1143) // whose namespace and name match those of aAttrSelector.  This function
  1144) // performs comparisons on the value only, based on aAttrSelector->mFunction.
  1145) static PRBool AttrMatchesValue(const nsAttrSelector* aAttrSelector,
                      ^ 357 
  1146)                                const nsString& aValue)
  1147) {
  1148)   NS_PRECONDITION(aAttrSelector, "Must have an attribute selector");
          ^ 357 
  1149) 
  1150)   // http://lists.w3.org/Archives/Public/www-style/2008Apr/0038.html
  1151)   // *= (CONTAINSMATCH) ~= (INCLUDES) ^= (BEGINSMATCH) $= (ENDSMATCH)
  1152)   // all accept the empty string, but match nothing.
  1153)   if (aAttrSelector->mValue.IsEmpty() &&
          ^ 714 (2/8)
  1154)       (aAttrSelector->mFunction == NS_ATTR_FUNC_INCLUDES ||
  1155)        aAttrSelector->mFunction == NS_ATTR_FUNC_ENDSMATCH ||
  1156)        aAttrSelector->mFunction == NS_ATTR_FUNC_BEGINSMATCH ||
  1157)        aAttrSelector->mFunction == NS_ATTR_FUNC_CONTAINSMATCH))
  1158)     return PR_FALSE;
            ^ 0 
  1159) 
  1160)   const nsDefaultStringComparator defaultComparator;
                                          ^ 357 
  1161)   const nsCaseInsensitiveStringComparator ciComparator;
                                                  ^ 357 
  1162)   const nsStringComparator& comparator = aAttrSelector->mCaseSensitive
                                               ^ 1,071 (3/4)
  1163)                 ? static_cast<const nsStringComparator&>(defaultComparator)
  1164)                 : static_cast<const nsStringComparator&>(ciComparator);
  1165)   switch (aAttrSelector->mFunction) {
          ^ 357 
  1166)     case NS_ATTR_FUNC_EQUALS: 
  1167)       return aValue.Equals(aAttrSelector->mValue, comparator);
              ^ 0 (3)
  1168)     case NS_ATTR_FUNC_INCLUDES: 
  1169)       return ValueIncludes(aValue, aAttrSelector->mValue, comparator);
              ^ 879 (3)
  1170)     case NS_ATTR_FUNC_DASHMATCH: 
  1171)       return nsStyleUtil::DashMatchCompare(aValue, aAttrSelector->mValue, comparator);
              ^ 0 (3)
  1172)     case NS_ATTR_FUNC_ENDSMATCH:
  1173)       return StringEndsWith(aValue, aAttrSelector->mValue, comparator);
              ^ 192 (3)
  1174)     case NS_ATTR_FUNC_BEGINSMATCH:
  1175)       return StringBeginsWith(aValue, aAttrSelector->mValue, comparator);
              ^ 0 (3)
  1176)     case NS_ATTR_FUNC_CONTAINSMATCH:
  1177)       return FindInReadable(aAttrSelector->mValue, aValue, comparator);
              ^ 0 (3)
  1178)     default:
  1179)       NS_NOTREACHED("Shouldn't be ending up here");
              ^ 0 
  1180)       return PR_FALSE;
              ^ 0 
  1181)   }
  1182) }
  1183) 
  1184) // NOTE: For |aStateMask| and |aAttribute| to work correctly, it's
  1185) // important that any change that changes multiple state bits and
  1186) // maybe an attribute include all those state bits and the attribute
  1187) // in the notification.  Otherwise, if multiple states change but we
  1188) // do separate notifications then we might determine the style is not
  1189) // state-dependent when it really is (e.g., determining that a
  1190) // :hover:active rule no longer matches when both states are unset).
  1191) 
  1192) // If |aForStyling| is false, we shouldn't mark slow-selector bits on nodes.
  1193) 
  1194) // |aDependence| has two functions:
  1195) //  * when non-null, it indicates that we're processing a negation,
  1196) //    which is done only when SelectorMatches calls itself recursively
  1197) //  * what it points to should be set to true whenever a test is skipped
  1198) //    because of aStateMask or aAttribute
  1199) static PRBool SelectorMatches(RuleProcessorData &data,
                      ^ 40,311,512 
  1200)                               nsCSSSelector* aSelector,
  1201)                               PRInt32 aStateMask, // states NOT to test
  1202)                               nsIAtom* aAttribute, // attribute NOT to test
  1203)                               PRBool aForStyling,
  1204)                               PRBool* const aDependence = nsnull) 
  1205) 
  1206) {
  1207)   // namespace/tag match
  1208)   if ((kNameSpaceID_Unknown != aSelector->mNameSpace &&
          ^ 94,139,863 (5)
  1209)        data.mNameSpaceID != aSelector->mNameSpace) ||
  1210)       (aSelector->mTag && aSelector->mTag != data.mContentTag)) {
  1211)     // optimization : bail out early if we can
  1212)     return PR_FALSE;
            ^ 4,672,505 
  1213)   }
  1214) 
  1215)   PRBool result = PR_TRUE;
                        ^ 35,639,007 
  1216)   const PRBool isNegated = (aDependence != nsnull);
                                 ^ 35,639,007 (2)
  1217)   // The selectors for which we set node bits are, unfortunately, early
  1218)   // in this function (because they're pseudo-classes, which are
  1219)   // generally quick to test, and thus earlier).  If they were later,
  1220)   // we'd probably avoid setting those bits in more cases where setting
  1221)   // them is unnecessary.
  1222)   const PRBool setNodeFlags = aForStyling && aStateMask == 0 && !aAttribute;
                                    ^ 142,515,359 (5)
  1223) 
  1224)   // test for pseudo class match
  1225)   // first-child, root, lang, active, focus, hover, link, visited...
  1226)   // XXX disabled, enabled, selected, selection
  1227)   for (nsPseudoClassList* pseudoClass = aSelector->mPseudoClassList;
          ^ 36,615,112 (3)                    ^ 35,639,007 
  1228)        pseudoClass && result; pseudoClass = pseudoClass->mNext) {
  1229)     PRInt32 stateToCheck = 0;
                                 ^ 431,460 
  1230)     if (nsCSSPseudoClasses::firstNode == pseudoClass->mAtom) {
            ^ 431,460 
  1231)       nsIContent *firstNode = nsnull;
                                    ^ 245 
  1232)       nsIContent *parent = data.mParentContent;
  1233)       if (parent) {
  1234)         if (setNodeFlags)
                ^ 245 
  1235)           parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
                  ^ 245 
  1236) 
  1237)         PRInt32 index = -1;
                              ^ 245 
  1238)         do {
  1239)           firstNode = parent->GetChildAt(++index);
                  ^ 584 (4)
  1240)           // stop at first non-comment and non-whitespace node
  1241)         } while (firstNode &&
                ^ 584 (2)
  1242)                  !IsSignificantChild(firstNode, PR_TRUE, PR_FALSE));
  1243)       }
  1244)       result = (data.mContent == firstNode);
              ^ 490 (3)
  1245)     }
  1246)     else if (nsCSSPseudoClasses::lastNode == pseudoClass->mAtom) {
                 ^ 862,430 (2)
  1247)       nsIContent *lastNode = nsnull;
                                   ^ 132 
  1248)       nsIContent *parent = data.mParentContent;
  1249)       if (parent) {
  1250)         if (setNodeFlags)
                ^ 132 
  1251)           parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
                  ^ 132 
  1252) 
  1253)         PRUint32 index = parent->GetChildCount();
                               ^ 264 (2)
  1254)         do {
  1255)           lastNode = parent->GetChildAt(--index);
                  ^ 296 (4)
  1256)           // stop at first non-comment and non-whitespace node
  1257)         } while (lastNode &&
                ^ 296 (2)
  1258)                  !IsSignificantChild(lastNode, PR_TRUE, PR_FALSE));
  1259)       }
  1260)       result = (data.mContent == lastNode);
              ^ 264 (3)
  1261)     }
  1262)     else if (nsCSSPseudoClasses::firstChild == pseudoClass->mAtom ||
                 ^ 2,586,362 (6)
  1263)              nsCSSPseudoClasses::lastChild == pseudoClass->mAtom ||
  1264)              nsCSSPseudoClasses::onlyChild == pseudoClass->mAtom) {
  1265)       nsIContent *parent = data.mParentContent;
                                 ^ 162 
  1266)       if (parent) {
  1267)         const PRBool checkFirst =
                                        ^ 324 (2)
  1268)           pseudoClass->mAtom != nsCSSPseudoClasses::lastChild;
  1269)         const PRBool checkLast =
                                       ^ 162 
  1270)           pseudoClass->mAtom != nsCSSPseudoClasses::firstChild;
  1271)         if (setNodeFlags)
  1272)           parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
                  ^ 162 
  1273) 
  1274)         result = (!checkFirst ||
                ^ 1,204 (10/11)
  1275)                   data.GetNthIndex(PR_FALSE, PR_FALSE, PR_TRUE) == 1) &&
  1276)                  (!checkLast ||
  1277)                   data.GetNthIndex(PR_FALSE, PR_TRUE, PR_TRUE) == 1);
  1278)       } else {
  1279)         result = PR_FALSE;
                ^ 0 
  1280)       }
  1281)     }
  1282)     else if (nsCSSPseudoClasses::nthChild == pseudoClass->mAtom ||
                 ^ 3,447,368 (8)
  1283)              nsCSSPseudoClasses::nthLastChild == pseudoClass->mAtom ||
  1284)              nsCSSPseudoClasses::nthOfType == pseudoClass->mAtom ||
  1285)              nsCSSPseudoClasses::nthLastOfType == pseudoClass->mAtom) {
  1286)       nsIContent *parent = data.mParentContent;
                                 ^ 0 
  1287)       if (parent) {
  1288)         PRBool isOfType =
                                ^ 0 (8)
  1289)           nsCSSPseudoClasses::nthOfType == pseudoClass->mAtom ||
  1290)           nsCSSPseudoClasses::nthLastOfType == pseudoClass->mAtom;
  1291)         PRBool isFromEnd =
                                 ^ 0 (7)
  1292)           nsCSSPseudoClasses::nthLastChild == pseudoClass->mAtom ||
  1293)           nsCSSPseudoClasses::nthLastOfType == pseudoClass->mAtom;
  1294)         if (setNodeFlags) {
  1295)           if (isFromEnd)
                  ^ 0 
  1296)             parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
                    ^ 0 
  1297)           else
  1298)             parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
                    ^ 0 
  1299)         }
  1300) 
  1301)         const PRInt32 index = data.GetNthIndex(isOfType, isFromEnd, PR_FALSE);
                                    ^ 0 (2)
  1302)         if (index <= 0) {
  1303)           // Node is anonymous content (not really a child of its parent).
  1304)           result = PR_FALSE;
                  ^ 0 
  1305)         } else {
  1306)           const PRInt32 a = pseudoClass->u.mNumbers[0];
                                  ^ 0 
  1307)           const PRInt32 b = pseudoClass->u.mNumbers[1];
  1308)           // result should be true if there exists n >= 0 such that
  1309)           // a * n + b == index.
  1310)           if (a == 0) {
  1311)             result = b == index;
                    ^ 0 (3)
  1312)           } else {
  1313)             // Integer division in C does truncation (towards 0).  So
  1314)             // check that the result is nonnegative, and that there was no
  1315)             // truncation.
  1316)             const PRInt32 n = (index - b) / a;
                                    ^ 0 
  1317)             result = n >= 0 && (a * n == index - b);
                    ^ 0 (3)
  1318)           }
  1319)         }
  1320)       } else {
  1321)         result = PR_FALSE;
                ^ 0 
  1322)       }
  1323)     }
  1324)     else if (nsCSSPseudoClasses::firstOfType == pseudoClass->mAtom ||
                 ^ 2,585,278 (6)
  1325)              nsCSSPseudoClasses::lastOfType == pseudoClass->mAtom ||
  1326)              nsCSSPseudoClasses::onlyOfType == pseudoClass->mAtom) {
  1327)       nsIContent *parent = data.mParentContent;
                                 ^ 62 
  1328)       if (parent) {
  1329)         const PRBool checkFirst =
                                        ^ 124 (2)
  1330)           pseudoClass->mAtom != nsCSSPseudoClasses::lastOfType;
  1331)         const PRBool checkLast =
                                       ^ 62 
  1332)           pseudoClass->mAtom != nsCSSPseudoClasses::firstOfType;
  1333)         if (setNodeFlags) {
  1334)           if (checkLast)
                  ^ 62 
  1335)             parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
                    ^ 0 
  1336)           else
  1337)             parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
                    ^ 62 
  1338)         }
  1339) 
  1340)         result = (!checkFirst ||
                ^ 372 (6/11)
  1341)                   data.GetNthIndex(PR_TRUE, PR_FALSE, PR_TRUE) == 1) &&
  1342)                  (!checkLast ||
  1343)                   data.GetNthIndex(PR_TRUE, PR_TRUE, PR_TRUE) == 1);
  1344)       } else {
  1345)         result = PR_FALSE;
                ^ 0 
  1346)       }
  1347)     }
  1348)     else if (nsCSSPseudoClasses::empty == pseudoClass->mAtom ||
                 ^ 1,723,250 (4)
  1349)              nsCSSPseudoClasses::mozOnlyWhitespace == pseudoClass->mAtom) {
  1350)       nsIContent *child = nsnull;
                                ^ 333 
  1351)       nsIContent *element = data.mContent;
  1352)       const PRBool isWhitespaceSignificant =
                                                   ^ 333 
  1353)         nsCSSPseudoClasses::empty == pseudoClass->mAtom;
  1354)       PRInt32 index = -1;
  1355) 
  1356)       if (setNodeFlags)
  1357)         element->SetFlags(NODE_HAS_EMPTY_SELECTOR);
                ^ 333 
  1358) 
  1359)       do {
  1360)         child = element->GetChildAt(++index);
                ^ 710 (4)
  1361)         // stop at first non-comment (and non-whitespace for
  1362)         // :-moz-only-whitespace) node        
  1363)       } while (child && !IsSignificantChild(child, PR_TRUE, isWhitespaceSignificant));
              ^ 360 (2)
  1364)       result = (child == nsnull);
              ^ 666 (3)
  1365)     }
  1366)     else if (nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname == pseudoClass->mAtom) {
                 ^ 861,052 (2)
  1367)       NS_ASSERTION(pseudoClass->u.mString, "Must have string!");
              ^ 0 
  1368)       nsIContent *child = nsnull;
                                ^ 0 
  1369)       nsIContent *element = data.mContent;
  1370)       PRInt32 index = -1;
  1371) 
  1372)       if (setNodeFlags)
  1373)         element->SetFlags(NODE_HAS_SLOW_SELECTOR);
                ^ 0 
  1374) 
  1375)       do {
  1376)         child = element->GetChildAt(++index);
                ^ 0 (2)
  1377)       } while (child &&
              ^ 0 (16)
  1378)                (!IsSignificantChild(child, PR_TRUE, PR_FALSE) ||
  1379)                 (child->GetNameSpaceID() == element->GetNameSpaceID() &&
  1380)                  child->Tag()->Equals(nsDependentString(pseudoClass->u.mString)))));
  1381)       result = (child == nsnull);
              ^ 0 (3)
  1382)     }
  1383)     else if (nsCSSPseudoClasses::mozSystemMetric == pseudoClass->mAtom) {
                 ^ 861,052 (2)
  1384)       if (!sSystemMetrics && !InitSystemMetrics()) {
              ^ 8,356 (3)
  1385)         return PR_FALSE;
                ^ 0 
  1386)       }
  1387)       NS_ASSERTION(pseudoClass->u.mString, "Must have string!");
              ^ 8,354 
  1388)       nsCOMPtr<nsIAtom> metric = do_GetAtom(pseudoClass->u.mString);
                                ^ 16,708 (2)
  1389)       result = sSystemMetrics->IndexOf(metric) !=
              ^ 25,062 (4)
  1390)                sSystemMetrics->NoIndex;
  1391)     }
            ^ 8,354 
  1392)     else if (nsCSSPseudoClasses::mozHasHandlerRef == pseudoClass->mAtom) {
                 ^ 844,344 (2)
  1393)       nsIContent *child = nsnull;
                                ^ 0 
  1394)       nsIContent *element = data.mContent;
  1395)       PRInt32 index = -1;
  1396) 
  1397)       result = PR_FALSE;
  1398)       if (element) {
  1399)         do {
  1400)           child = element->GetChildAt(++index);
                  ^ 0 (2)
  1401)           if (child && child->IsNodeOfType(nsINode::eHTML) &&
                  ^ 0 (13)
  1402)               child->Tag() == nsGkAtoms::param &&
  1403)               child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
  1404)                                  NS_LITERAL_STRING("pluginurl"), eIgnoreCase)) {
  1405)             result = PR_TRUE;
                    ^ 0 
  1406)             break;
  1407)           }
  1408)         } while (child);
                ^ 0 
  1409)       }
  1410)     }
  1411)     else if (nsCSSPseudoClasses::root == pseudoClass->mAtom) {
                 ^ 844,344 (2)
  1412)       result = (data.mParentContent == nsnull &&
              ^ 27,459 (8/9)
  1413)                 data.mContent &&
  1414)                 data.mContent ==
  1415)                   data.mContent->GetOwnerDoc()->GetRootContent());
  1416)     }
  1417)     else if (nsCSSPseudoClasses::mozBoundElement == pseudoClass->mAtom) {
                 ^ 826,070 (2)
  1418)       // XXXldb How do we know where the selector came from?  And what
  1419)       // if there are multiple bindings, and we should be matching the
  1420)       // outer one?
  1421)       result = (data.mScopedRoot && data.mScopedRoot == data.mContent);
              ^ 0 (4)
  1422)     }
  1423)     else if (nsCSSPseudoClasses::lang == pseudoClass->mAtom) {
                 ^ 826,070 (2)
  1424)       NS_ASSERTION(nsnull != pseudoClass->u.mString, "null lang parameter");
              ^ 0 
  1425)       result = PR_FALSE;
              ^ 0 
  1426)       if (pseudoClass->u.mString && *pseudoClass->u.mString) {
              ^ 0 
  1427)         // We have to determine the language of the current element.  Since
  1428)         // this is currently no property and since the language is inherited
  1429)         // from the parent we have to be prepared to look at all parent
  1430)         // nodes.  The language itself is encoded in the LANG attribute.
  1431)         const nsString* lang = data.GetLang();
                                     ^ 0 (2)
  1432)         if (lang && !lang->IsEmpty()) { // null check for out-of-memory
                ^ 0 (2)
  1433)           result = nsStyleUtil::DashMatchCompare(*lang,
                  ^ 0 (4)
  1434)                                     nsDependentString(pseudoClass->u.mString), 
  1435)                                     nsCaseInsensitiveStringComparator());
  1436)         }
  1437)         else if (data.mContent) {
                     ^ 0 
  1438)           nsIDocument* doc = data.mContent->GetDocument();
                                   ^ 0 (2)
  1439)           if (doc) {
  1440)             // Try to get the language from the HTTP header or if this
  1441)             // is missing as well from the preferences.
  1442)             // The content language can be a comma-separated list of
  1443)             // language codes.
  1444)             nsAutoString language;
                                 ^ 0 
  1445)             doc->GetContentLanguage(language);
                    ^ 0 
  1446) 
  1447)             nsDependentString langString(pseudoClass->u.mString);
                                      ^ 0 
  1448)             language.StripWhitespace();
                    ^ 0 
  1449)             PRInt32 begin = 0;
                                  ^ 0 
  1450)             PRInt32 len = language.Length();
                                ^ 0 
  1451)             while (begin < len) {
                    ^ 0 (2)
  1452)               PRInt32 end = language.FindChar(PRUnichar(','), begin);
                                  ^ 0 (2)
  1453)               if (end == kNotFound) {
  1454)                 end = len;
                        ^ 0 
  1455)               }
  1456)               if (nsStyleUtil::DashMatchCompare(Substring(language, begin, end-begin),
                      ^ 0 (5)
  1457)                                    langString,
  1458)                                    nsCaseInsensitiveStringComparator())) {
  1459)                 result = PR_TRUE;
                        ^ 0 
  1460)                 break;
  1461)               }
  1462)               begin = end + 1;
  1463)             }
  1464)           }
                  ^ 0 (2)
  1465)         }
  1466)       }
  1467)     } else if (nsCSSPseudoClasses::active == pseudoClass->mAtom) {
                   ^ 826,070 (2)
  1468)       stateToCheck = NS_EVENT_STATE_ACTIVE;
              ^ 26,091 
  1469)     }
  1470)     else if (nsCSSPseudoClasses::focus == pseudoClass->mAtom) {
                 ^ 773,888 (2)
  1471)       stateToCheck = NS_EVENT_STATE_FOCUS;
              ^ 43,661 
  1472)     }
  1473)     else if (nsCSSPseudoClasses::hover == pseudoClass->mAtom) {
                 ^ 686,566 (2)
  1474)       stateToCheck = NS_EVENT_STATE_HOVER;
              ^ 74,311 
  1475)     }
  1476)     else if (nsCSSPseudoClasses::mozDragOver == pseudoClass->mAtom) {
                 ^ 537,944 (2)
  1477)       stateToCheck = NS_EVENT_STATE_DRAGOVER;
              ^ 0 
  1478)     }
  1479)     else if (nsCSSPseudoClasses::target == pseudoClass->mAtom) {
                 ^ 537,944 (2)
  1480)       stateToCheck = NS_EVENT_STATE_URLTARGET;
              ^ 0 
  1481)     }
  1482)     else if (IsLinkPseudo(pseudoClass->mAtom)) {
                 ^ 806,916 (3)
  1483)       if (data.mIsLink) {
              ^ 266,901 
  1484)         if (nsCSSPseudoClasses::mozAnyLink == pseudoClass->mAtom) {
                ^ 2,632 (2)
  1485)           result = PR_TRUE;
                  ^ 528 
  1486)         }
  1487)         else {
  1488)           NS_ASSERTION(nsCSSPseudoClasses::link == pseudoClass->mAtom ||
                  ^ 788 
  1489)                        nsCSSPseudoClasses::visited == pseudoClass->mAtom,
  1490)                        "somebody changed IsLinkPseudo");
  1491)           NS_ASSERTION(data.mLinkState == eLinkState_Unvisited ||
                  ^ 788 
  1492)                        data.mLinkState == eLinkState_Visited,
  1493)                        "unexpected link state for mIsLink");
  1494)           if (aStateMask & NS_EVENT_STATE_VISITED) {
                  ^ 788 
  1495)             result = PR_TRUE;
                    ^ 0 
  1496)             if (aDependence)
  1497)               *aDependence = PR_TRUE;
                      ^ 0 
  1498)           } else {
  1499)             result = ((eLinkState_Unvisited == data.mLinkState) ==
                    ^ 2,364 (4)
  1500)                       (nsCSSPseudoClasses::link == pseudoClass->mAtom));
  1501)           }
  1502)         }
  1503)       }
  1504)       else {
  1505)         result = PR_FALSE;  // not a link
                ^ 265,585 
  1506)       }
  1507)     }
  1508)     else if (nsCSSPseudoClasses::checked == pseudoClass->mAtom) {
                 ^ 4,142 (2)
  1509)       // This pseudoclass matches the selected state on the following elements:
  1510)       //  <option>
  1511)       //  <input type=checkbox>
  1512)       //  <input type=radio>
  1513)       stateToCheck = NS_EVENT_STATE_CHECKED;
              ^ 12 
  1514)     }
  1515)     else if (nsCSSPseudoClasses::enabled == pseudoClass->mAtom) {
                 ^ 4,118 (2)
  1516)       stateToCheck = NS_EVENT_STATE_ENABLED;
              ^ 0 
  1517)     }
  1518)     else if (nsCSSPseudoClasses::disabled == pseudoClass->mAtom) {
                 ^ 4,118 (2)
  1519)       stateToCheck = NS_EVENT_STATE_DISABLED;
              ^ 0 
  1520)     }    
  1521)     else if (nsCSSPseudoClasses::mozBroken == pseudoClass->mAtom) {
                 ^ 4,118 (2)
  1522)       stateToCheck = NS_EVENT_STATE_BROKEN;
              ^ 186 
  1523)     }
  1524)     else if (nsCSSPseudoClasses::mozUserDisabled == pseudoClass->mAtom) {
                 ^ 3,746 (2)
  1525)       stateToCheck = NS_EVENT_STATE_USERDISABLED;
              ^ 186 
  1526)     }
  1527)     else if (nsCSSPseudoClasses::mozSuppressed == pseudoClass->mAtom) {
                 ^ 3,374 (2)
  1528)       stateToCheck = NS_EVENT_STATE_SUPPRESSED;
              ^ 697 
  1529)     }
  1530)     else if (nsCSSPseudoClasses::mozLoading == pseudoClass->mAtom) {
                 ^ 1,980 (2)
  1531)       stateToCheck = NS_EVENT_STATE_LOADING;
              ^ 188 
  1532)     }
  1533)     else if (nsCSSPseudoClasses::mozTypeUnsupported == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1534)       stateToCheck = NS_EVENT_STATE_TYPE_UNSUPPORTED;
              ^ 0 
  1535)     }
  1536)     else if (nsCSSPseudoClasses::mozHandlerDisabled == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1537)       stateToCheck = NS_EVENT_STATE_HANDLER_DISABLED;
              ^ 0 
  1538)     }
  1539)     else if (nsCSSPseudoClasses::mozHandlerBlocked == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1540)       stateToCheck = NS_EVENT_STATE_HANDLER_BLOCKED;
              ^ 0 
  1541)     }
  1542)     else if (nsCSSPseudoClasses::defaultPseudo == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1543)       stateToCheck = NS_EVENT_STATE_DEFAULT;
              ^ 0 
  1544)     }
  1545)     else if (nsCSSPseudoClasses::required == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1546)       stateToCheck = NS_EVENT_STATE_REQUIRED;
              ^ 0 
  1547)     }
  1548)     else if (nsCSSPseudoClasses::optional == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1549)       stateToCheck = NS_EVENT_STATE_OPTIONAL;
              ^ 0 
  1550)     }
  1551)     else if (nsCSSPseudoClasses::valid == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1552)       stateToCheck = NS_EVENT_STATE_VALID;
              ^ 0 
  1553)     }
  1554)     else if (nsCSSPseudoClasses::invalid == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1555)       stateToCheck = NS_EVENT_STATE_INVALID;
              ^ 0 
  1556)     }
  1557)     else if (nsCSSPseudoClasses::inRange == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1558)       stateToCheck = NS_EVENT_STATE_INRANGE;
              ^ 0 
  1559)     }
  1560)     else if (nsCSSPseudoClasses::outOfRange == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1561)       stateToCheck = NS_EVENT_STATE_OUTOFRANGE;
              ^ 0 
  1562)     }
  1563)     else if (nsCSSPseudoClasses::mozReadOnly == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1564)       stateToCheck = NS_EVENT_STATE_MOZ_READONLY;
              ^ 0 
  1565)     }
  1566)     else if (nsCSSPseudoClasses::mozReadWrite == pseudoClass->mAtom) {
                 ^ 1,604 (2)
  1567)       stateToCheck = NS_EVENT_STATE_MOZ_READWRITE;
              ^ 767 
  1568)     }
  1569)     else if (nsCSSPseudoClasses::indeterminate == pseudoClass->mAtom) {
                 ^ 70 (2)
  1570)       stateToCheck = NS_EVENT_STATE_INDETERMINATE;
              ^ 0 
  1571)     }
  1572)     else if (nsCSSPseudoClasses::mozIsHTML == pseudoClass->mAtom) {
                 ^ 70 (2)
  1573)       result = data.mIsHTMLContent &&
              ^ 175 (5/7)
  1574)         data.mContent->GetNameSpaceID() == kNameSpaceID_None;
  1575)     }
  1576) #ifdef MOZ_MATHML
  1577)     else if (nsCSSPseudoClasses::mozMathIncrementScriptLevel == pseudoClass->mAtom) {
                 ^ 0 (2)
  1578)       stateToCheck = NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL;
              ^ 0 
  1579)     }
  1580) #endif
  1581)     else {
  1582)       NS_ERROR("CSS parser parsed a pseudo-class that we do not handle");
              ^ 0 
  1583)       result = PR_FALSE;  // unknown pseudo class
              ^ 0 
  1584)     }
  1585)     if (stateToCheck) {
            ^ 431,460 
  1586)       // check if the element is event-sensitive for :hover and :active
  1587)       if ((stateToCheck & (NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE)) &&
              ^ 370,709 (11)
  1588)           data.mCompatMode == eCompatibility_NavQuirks &&
  1589)           // global selector (but don't check .class):
  1590)           !aSelector->mTag && !aSelector->mIDList && !aSelector->mAttrList &&
  1591)           // This (or the other way around) both make :not() asymmetric
  1592)           // in quirks mode (and it's hard to work around since we're
  1593)           // testing the current mNegations, not the first
  1594)           // (unnegated)). This at least makes it closer to the spec.
  1595)           !isNegated &&
  1596)           // important for |IsQuirkEventSensitive|:
  1597)           data.mIsHTMLContent && !data.mIsLink &&
  1598)           !IsQuirkEventSensitive(data.mContentTag)) {
  1599)         // In quirks mode, only make certain elements sensitive to
  1600)         // selectors ":hover" and ":active".
  1601)         result = PR_FALSE;
                ^ 9,100 
  1602)       } else {
  1603)         if (aStateMask & stateToCheck) {
                ^ 136,999 
  1604)           result = PR_TRUE;
                  ^ 26,846 
  1605)           if (aDependence)
  1606)             *aDependence = PR_TRUE;
                    ^ 0 
  1607)         } else {
  1608)           result = (0 != (data.mEventState & stateToCheck));
                  ^ 220,306 (3)
  1609)         }
  1610)       }
  1611)     }
  1612)   }
  1613) 
  1614)   if (result && aSelector->mAttrList) {
          ^ 70,882,345 (2)
  1615)     // test for attribute match
  1616)     if (!data.mHasAttributes && !aAttribute) {
            ^ 316,174 (2)
  1617)       // if no attributes on the content, no match
  1618)       result = PR_FALSE;
              ^ 36,038 
  1619)     } else {
  1620)       NS_ASSERTION(data.mContent,
              ^ 244,098 
  1621)                    "Must have content if either data.mHasAttributes or "
  1622)                    "aAttribute is set!");
  1623)       result = PR_TRUE;
              ^ 244,098 
  1624)       nsAttrSelector* attr = aSelector->mAttrList;
  1625)       do {
  1626)         if (attr->mAttr == aAttribute) {
                ^ 507,370 (2)
  1627)           // XXX we should really have a namespace, not just an attr
  1628)           // name, in HasAttributeDependentStyle!
  1629)           result = PR_TRUE;
                  ^ 12,251 
  1630)           if (aDependence)
  1631)             *aDependence = PR_TRUE;
                    ^ 144 
  1632)         }
  1633)         else if (attr->mNameSpace == kNameSpaceID_Unknown) {
                     ^ 241,434 
  1634)           // Attr selector with a wildcard namespace.  We have to examine all
  1635)           // the attributes on our content node....  This sort of selector is
  1636)           // essentially a boolean OR, over all namespaces, of equivalent attr
  1637)           // selectors with those namespaces.  So to evaluate whether it
  1638)           // matches, evaluate for each namespace (the only namespaces that
  1639)           // have a chance at matching, of course, are ones that the element
  1640)           // actually has attributes in), short-circuiting if we ever match.
  1641)           PRUint32 attrCount = data.mContent->GetAttrCount();
                                     ^ 0 (2)
  1642)           result = PR_FALSE;
  1643)           for (PRUint32 i = 0; i < attrCount; ++i) {
                  ^ 0 (2)
  1644)             const nsAttrName* attrName =
                                               ^ 0 (2)
  1645)               data.mContent->GetAttrNameAt(i);
  1646)             NS_ASSERTION(attrName, "GetAttrCount lied or GetAttrNameAt failed");
                    ^ 0 
  1647)             if (attrName->LocalName() != attr->mAttr) {
                    ^ 0 (3)
  1648)               continue;
  1649)             }
  1650)             if (attr->mFunction == NS_ATTR_FUNC_SET) {
                    ^ 0 
  1651)               result = PR_TRUE;
                      ^ 0 
  1652)             } else {
  1653)               nsAutoString value;
                                   ^ 0 
  1654) #ifdef DEBUG
  1655)               PRBool hasAttr =
  1656) #endif
  1657)                 data.mContent->GetAttr(attrName->NamespaceID(),
                        ^ 0 (3)
  1658)                                        attrName->LocalName(), value);
  1659)               NS_ASSERTION(hasAttr, "GetAttrNameAt lied");
                      ^ 0 
  1660)               result = AttrMatchesValue(attr, value);
                      ^ 0 (2)
  1661)             }
  1662) 
  1663)             // At this point |result| has been set by us
  1664)             // explicitly in this loop.  If it's PR_FALSE, we may still match
  1665)             // -- the content may have another attribute with the same name but
  1666)             // in a different namespace.  But if it's PR_TRUE, we are done (we
  1667)             // can short-circuit the boolean OR described above).
  1668)             if (result) {
                    ^ 0 
  1669)               break;
  1670)             }
  1671)           }
  1672)         }
  1673)         else if (attr->mFunction == NS_ATTR_FUNC_EQUALS) {
                     ^ 241,434 
  1674)           result =
                  ^ 1,009,380 (6)
  1675)             data.mContent->
  1676)               AttrValueIs(attr->mNameSpace, attr->mAttr, attr->mValue,
  1677)                           attr->mCaseSensitive ? eCaseMatters : eIgnoreCase);
  1678)         }
  1679)         else if (!data.mContent->HasAttr(attr->mNameSpace, attr->mAttr)) {
                     ^ 118,674 (3)
  1680)           result = PR_FALSE;
                  ^ 38,415 
  1681)         }
  1682)         else if (attr->mFunction != NS_ATTR_FUNC_SET) {
                     ^ 1,143 
  1683)           nsAutoString value;
                               ^ 357 
  1684) #ifdef DEBUG
  1685)           PRBool hasAttr =
  1686) #endif
  1687)               data.mContent->GetAttr(attr->mNameSpace, attr->mAttr, value);
                      ^ 714 (2)
  1688)           NS_ASSERTION(hasAttr, "HasAttr lied");
                  ^ 357 
  1689)           result = AttrMatchesValue(attr, value);
                  ^ 714 (2)
  1690)         }
  1691)         
  1692)         attr = attr->mNext;
                ^ 253,685 
  1693)       } while (attr && result);
              ^ 28,546 
  1694)     }
  1695)   }
  1696)   nsAtomList* IDList = aSelector->mIDList;
                             ^ 35,639,007 
  1697)   if (result && IDList) {
          ^ 35,000,057 
  1698)     // test for ID match
  1699)     result = PR_FALSE;
            ^ 3,079,701 
  1700) 
  1701)     if (aAttribute && aAttribute == data.mContent->GetIDAttributeName()) {
            ^ 16,960 (2)
  1702)       result = PR_TRUE;
              ^ 266 
  1703)       if (aDependence)
  1704)         *aDependence = PR_TRUE;
                ^ 2 
  1705)     }
  1706)     else if (nsnull != data.mContentID) {
                 ^ 3,079,435 
  1707)       // case sensitivity: bug 93371
  1708)       const PRBool isCaseSensitive =
                                           ^ 2,966,716 (3)
  1709)         data.mCompatMode != eCompatibility_NavQuirks;
  1710) 
  1711)       result = PR_TRUE;
              ^ 1,483,358 
  1712)       if (isCaseSensitive) {
  1713)         do {
  1714)           if (IDList->mAtom != data.mContentID) {
                  ^ 48,518 (2)
  1715)             result = PR_FALSE;
                    ^ 21,988 
  1716)             break;
  1717)           }
  1718)           IDList = IDList->mNext;
                  ^ 2,271 
  1719)         } while (IDList);
  1720)       } else {
  1721)         const char* id1Str;
  1722)         data.mContentID->GetUTF8String(&id1Str);
                ^ 1,459,099 
  1723)         nsDependentCString id1(id1Str);
                                   ^ 1,459,099 
  1724)         do {
  1725)           const char* id2Str;
  1726)           IDList->mAtom->GetUTF8String(&id2Str);
                  ^ 2,918,198 (2)
  1727)           if (!id1.Equals(id2Str, nsCaseInsensitiveCStringComparator())) {
                  ^ 4,377,297 (3)
  1728)             result = PR_FALSE;
                    ^ 1,455,376 
  1729)             break;
  1730)           }
  1731)           IDList = IDList->mNext;
                  ^ 3,723 
  1732)         } while (IDList);
  1733)       }
              ^ 1,459,099 
  1734)     }
  1735)   }
  1736)     
  1737)   if (result && aSelector->mClassList) {
          ^ 67,565,623 (2)
  1738)     // test for class match
  1739)     if (aAttribute && aAttribute == data.mContent->GetClassAttributeName()) {
            ^ 31,879,177 (3)
  1740)       result = PR_TRUE;
              ^ 939,186 
  1741)       if (aDependence)
  1742)         *aDependence = PR_TRUE;
                ^ 0 
  1743)     }
  1744)     else {
  1745)       // case sensitivity: bug 93371
  1746)       const PRBool isCaseSensitive =
                                           ^ 58,119,774 (3)
  1747)         data.mCompatMode != eCompatibility_NavQuirks;
  1748) 
  1749)       nsAtomList* classList = aSelector->mClassList;
                                    ^ 29,059,887 
  1750)       const nsAttrValue *elementClasses = data.mClasses;
  1751)       while (nsnull != classList) {
              ^ 29,277,540 (2)
  1752)         if (!(elementClasses && elementClasses->Contains(classList->mAtom, isCaseSensitive ? eCaseMatters : eIgnoreCase))) {
                ^ 138,905,271 (11)
  1753)           result = PR_FALSE;
                  ^ 28,842,234 
  1754)           break;
  1755)         }
  1756)         classList = classList->mNext;
  1757)       }
  1758)     }
  1759)   }
  1760)   
  1761)   // apply SelectorMatches to the negated selectors in the chain
  1762)   if (!isNegated) {
          ^ 35,639,007 
  1763)     for (nsCSSSelector *negation = aSelector->mNegations;
            ^ 38,727,785 (3)             ^ 35,629,985 
  1764)          result && negation; negation = negation->mNegations) {
  1765)       PRBool dependence = PR_FALSE;
                                ^ 9,022 
  1766)       result = !SelectorMatches(data, negation, aStateMask,
              ^ 18,044 (3)
  1767)                                 aAttribute, aForStyling, &dependence);
  1768)       // If the selector does match due to the dependence on aStateMask
  1769)       // or aAttribute, then we want to keep result true so that the
  1770)       // final result of SelectorMatches is true.  Doing so tells
  1771)       // StateEnumFunc or AttributeEnumFunc that there is a dependence
  1772)       // on the state or attribute.
  1773)       result = result || dependence;
              ^ 20,430 (4)
  1774)     }
  1775)   }
  1776)   return result;
          ^ 35,639,007 
  1777) }
  1778) 
  1779) #undef STATE_CHECK
  1780) 
  1781) // Right now, there are four operators:
  1782) //   PRUnichar(0), the descendant combinator, is greedy
  1783) //   '~', the indirect adjacent sibling combinator, is greedy
  1784) //   '+' and '>', the direct adjacent sibling and child combinators, are not
  1785) #define NS_IS_GREEDY_OPERATOR(ch) (ch == PRUnichar(0) || ch == PRUnichar('~'))
  1786) 
  1787) static PRBool SelectorMatchesTree(RuleProcessorData& aPrevData,
                      ^ 2,783,365 
  1788)                                   nsCSSSelector* aSelector,
  1789)                                   PRBool aForStyling) 
  1790) {
  1791)   nsCSSSelector* selector = aSelector;
  1792)   RuleProcessorData* prevdata = &aPrevData;
  1793)   while (selector) { // check compound selectors
          ^ 37,381,663 (2)
  1794)     // If we don't already have a RuleProcessorData for the next
  1795)     // appropriate content (whether parent or previous sibling), create
  1796)     // one.
  1797) 
  1798)     // for adjacent sibling combinators, the content to test against the
  1799)     // selector is the previous sibling *element*
  1800)     RuleProcessorData* data;
  1801)     if (PRUnichar('+') == selector->mOperator ||
            ^ 74,640,434 (2)
  1802)         PRUnichar('~') == selector->mOperator) {
  1803)       data = prevdata->mPreviousSiblingData;
              ^ 185 
  1804)       if (!data) {
  1805)         nsIContent* content = prevdata->mContent;
                                    ^ 185 
  1806)         nsIContent* parent = content->GetParent();
                                   ^ 185 
  1807)         if (parent) {
  1808)           parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
                  ^ 185 
  1809) 
  1810)           PRInt32 index = parent->IndexOf(content);
                                ^ 370 (2)
  1811)           while (0 <= --index) {
                  ^ 185 (1/2)
  1812)             content = parent->GetChildAt(index);
                    ^ 110 (2)
  1813)             if (content->IsNodeOfType(nsINode::eELEMENT)) {
                    ^ 55 
  1814)               data = RuleProcessorData::Create(prevdata->mPresContext, content,
                      ^ 110 (2)
  1815)                                                prevdata->mRuleWalker,
  1816)                                                prevdata->mCompatMode);
  1817)               prevdata->mPreviousSiblingData = data;    
  1818)               break;
  1819)             }
  1820)           }
  1821)         }
  1822)       }
  1823)     }
  1824)     // for descendant combinators and child combinators, the content
  1825)     // to test against is the parent
  1826)     else {
  1827)       data = prevdata->mParentData;
              ^ 37,320,032 
  1828)       if (!data) {
  1829)         nsIContent *content = prevdata->mContent->GetParent();
                                    ^ 6,237,570 (2)
  1830)         // GetParent could return a document fragment; we only want
  1831)         // element parents.
  1832)         if (content && content->IsNodeOfType(nsINode::eELEMENT)) {
                ^ 1,194,516 (2)
  1833)           data = RuleProcessorData::Create(prevdata->mPresContext, content,
                  ^ 1,194,516 (2)
  1834)                                            prevdata->mRuleWalker,
  1835)                                            prevdata->mCompatMode);
  1836)           prevdata->mParentData = data;    
  1837)         }
  1838)       }
  1839)     }
  1840)     if (! data) {
            ^ 37,320,217 
  1841)       return PR_FALSE;
              ^ 2,521,657 
  1842)     }
  1843)     if (SelectorMatches(*data, selector, 0, nsnull, aForStyling)) {
            ^ 69,597,120 (2)
  1844)       // to avoid greedy matching, we need to recur if this is a
  1845)       // descendant or general sibling combinator and the next
  1846)       // combinator is different, but we can make an exception for
  1847)       // sibling, then parent, since a sibling's parent is always the
  1848)       // same.
  1849)       if ((NS_IS_GREEDY_OPERATOR(selector->mOperator)) &&
              ^ 411,124 (4/6)
  1850)           (selector->mNext) &&
  1851)           (selector->mNext->mOperator != selector->mOperator) &&
  1852)           !(selector->mOperator == '~' &&
  1853)             selector->mNext->mOperator == PRUnichar(0))) {
  1854) 
  1855)         // pretend the selector didn't match, and step through content
  1856)         // while testing the same selector
  1857) 
  1858)         // This approach is slightly strange in that when it recurs
  1859)         // it tests from the top of the content tree, down.  This
  1860)         // doesn't matter much for performance since most selectors
  1861)         // don't match.  (If most did, it might be faster...)
  1862)         if (SelectorMatchesTree(*data, selector, aForStyling)) {
                ^ 0 (2)
  1863)           return PR_TRUE;
                  ^ 0 
  1864)         }
  1865)       }
  1866)       selector = selector->mNext;
              ^ 117,714 
  1867)     }
  1868)     else {
  1869)       // for adjacent sibling and child combinators, if we didn't find
  1870)       // a match, we're done
  1871)       if (!NS_IS_GREEDY_OPERATOR(selector->mOperator)) {
              ^ 34,881,108 (2)
  1872)         return PR_FALSE;  // parent was required to match
                ^ 200,262 
  1873)       }
  1874)     }
  1875)     prevdata = data;
  1876)   }
  1877)   return PR_TRUE; // all the selectors matched.
          ^ 61,446 
  1878) }
  1879) 
  1880) static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
                    ^ 2,584,135 
  1881)                             void* aData)
  1882) {
  1883)   ElementRuleProcessorData* data = (ElementRuleProcessorData*)aData;
  1884) 
  1885)   if (SelectorMatches(*data, aSelector, 0, nsnull, PR_TRUE)) {
          ^ 2,584,135 
  1886)     nsCSSSelector *next = aSelector->mNext;
                                ^ 2,019,108 
  1887)     if (!next || SelectorMatchesTree(*data, next, PR_TRUE)) {
            ^ 3,680,968 (2)
  1888)       // for performance, require that every implementation of
  1889)       // nsICSSStyleRule return the same pointer for nsIStyleRule (why
  1890)       // would anything multiply inherit nsIStyleRule anyway?)
  1891) #ifdef DEBUG
  1892)       nsCOMPtr<nsIStyleRule> iRule = do_QueryInterface(aRule);
  1893)       NS_ASSERTION(static_cast<nsIStyleRule*>(aRule) == iRule.get(),
  1894)                    "Please fix QI so this performance optimization is valid");
  1895) #endif
  1896)       data->mRuleWalker->Forward(static_cast<nsIStyleRule*>(aRule));
              ^ 227,664 
  1897)       // nsStyleSet will deal with the !important rule
  1898)     }
  1899)   }
  1900) }
        ^ 2,584,135 
  1901) 
  1902) NS_IMETHODIMP
  1903) nsCSSRuleProcessor::RulesMatching(ElementRuleProcessorData *aData)
                            ^ 135,147 
  1904) {
  1905)   NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT),
          ^ 135,147 
  1906)                   "content must be element");
  1907) 
  1908)   RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
                                   ^ 270,294 (2)
  1909) 
  1910)   if (cascade) {
  1911)     cascade->mRuleHash.EnumerateAllRules(aData->mNameSpaceID,
            ^ 135,147 
  1912)                                          aData->mContentTag,
  1913)                                          aData->mContentID,
  1914)                                          aData->mClasses,
  1915)                                          ContentEnumFunc,
  1916)                                          aData);
  1917)   }
  1918)   return NS_OK;
          ^ 135,147 
  1919) }
  1920) 
  1921) static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
                    ^ 1,292,423 
  1922)                            void* aData)
  1923) {
  1924)   PseudoRuleProcessorData* data = (PseudoRuleProcessorData*)aData;
  1925) 
  1926)   NS_ASSERTION(aSelector->mTag == data->mPseudoTag, "RuleHash failure");
          ^ 1,292,423 
  1927)   PRBool matches = PR_TRUE;
                         ^ 1,292,423 
  1928)   if (data->mComparator)
  1929)     data->mComparator->PseudoMatches(data->mPseudoTag, aSelector, &matches);
            ^ 0 
  1930) 
  1931)   if (matches) {
          ^ 1,292,423 
  1932)     nsCSSSelector *selector = aSelector->mNext;
                                    ^ 1,292,423 
  1933) 
  1934)     if (selector) { // test next selector specially
  1935)       if (PRUnichar('+') == selector->mOperator) {
              ^ 1,257,115 
  1936)         return; // not valid here, can't match
                ^ 0 
  1937)       }
  1938)       if (SelectorMatches(*data, selector, 0, nsnull, PR_TRUE)) {
              ^ 2,514,230 (2)
  1939)         selector = selector->mNext;
                ^ 54 
  1940)       }
  1941)       else {
  1942)         if (PRUnichar('>') == selector->mOperator) {
                ^ 1,257,061 
  1943)           return; // immediate parent didn't match
                  ^ 1,257,061 
  1944)         }
  1945)       }
  1946)     }
  1947) 
  1948)     if (selector && 
            ^ 35,364 (3)
  1949)         (! SelectorMatchesTree(*data, selector, PR_TRUE))) {
  1950)       return; // remaining selectors didn't match
              ^ 1 
  1951)     }
  1952) 
  1953)     // for performance, require that every implementation of
  1954)     // nsICSSStyleRule return the same pointer for nsIStyleRule (why
  1955)     // would anything multiply inherit nsIStyleRule anyway?)
  1956) #ifdef DEBUG
  1957)     nsCOMPtr<nsIStyleRule> iRule = do_QueryInterface(aRule);
  1958)     NS_ASSERTION(static_cast<nsIStyleRule*>(aRule) == iRule.get(),
  1959)                  "Please fix QI so this performance optimization is valid");
  1960) #endif
  1961)     data->mRuleWalker->Forward(static_cast<nsIStyleRule*>(aRule));
            ^ 35,361 
  1962)     // nsStyleSet will deal with the !important rule
  1963)   }
  1964) }
        ^ 35,361 
  1965) 
  1966) NS_IMETHODIMP
  1967) nsCSSRuleProcessor::RulesMatching(PseudoRuleProcessorData* aData)
                            ^ 718,369 
  1968) {
  1969)   NS_PRECONDITION(!aData->mContent ||
          ^ 718,369 
  1970)                   aData->mContent->IsNodeOfType(nsINode::eELEMENT),
  1971)                   "content (if present) must be element");
  1972) 
  1973)   RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
                                   ^ 1,436,738 (2)
  1974) 
  1975)   if (cascade) {
  1976)     cascade->mRuleHash.EnumerateTagRules(aData->mPseudoTag,
            ^ 718,369 
  1977)                                          PseudoEnumFunc, aData);
  1978)   }
  1979)   return NS_OK;
          ^ 718,369 
  1980) }
  1981) 
  1982) inline PRBool
  1983) IsSiblingOperator(PRUnichar oper)
        ^ 12,185,324 
  1984) {
  1985)   return oper == PRUnichar('+') || oper == PRUnichar('~');
          ^ 36,555,916 (4)
  1986) }
  1987) 
  1988) NS_IMETHODIMP
  1989) nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData,
                            ^ 1,821 
  1990)                                            nsReStyleHint* aResult)
  1991) {
  1992)   NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT),
          ^ 1,821 
  1993)                   "content must be element");
  1994) 
  1995)   RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
                                   ^ 3,642 (2)
  1996) 
  1997)   // Look up the content node in the state rule list, which points to
  1998)   // any (CSS2 definition) simple selector (whether or not it is the
  1999)   // subject) that has a state pseudo-class on it.  This means that this
  2000)   // code will be matching selectors that aren't real selectors in any
  2001)   // stylesheet (e.g., if there is a selector "body > p:hover > a", then
  2002)   // "body > p:hover" will be in |cascade->mStateSelectors|).  Note that
  2003)   // |IsStateSelector| below determines which selectors are in
  2004)   // |cascade->mStateSelectors|.
  2005)   if (cascade) {
  2006)     *aResult = nsReStyleHint(0);
            ^ 1,821 
  2007)     nsCSSSelector **iter = cascade->mStateSelectors.Elements(),
                                 ^ 1,821 
  2008)                   **end = iter + cascade->mStateSelectors.Length();
                                ^ 1,821 
  2009)     for(; iter != end; ++iter) {
            ^ 112,732 (2)
  2010)       nsCSSSelector* selector = *iter;
                                      ^ 110,911 
  2011) 
  2012)       nsReStyleHint possibleChange = IsSiblingOperator(selector->mOperator) ?
                                           ^ 443,644 (5/6)
  2013)         eReStyle_LaterSiblings :
  2014)         (selector->mIsNextOfSomething ? eReStyle_Subtree : eReStyle_Self);
  2015) 
  2016)       // If *aResult already includes all the bits of possibleChange,
  2017)       // don't bother calling SelectorMatches, since even if it returns false
  2018)       // *aResult won't change.
  2019)       if ((possibleChange & ~(*aResult)) &&
              ^ 206,246 (4)
  2020)           SelectorMatches(*aData, selector, aData->mStateMask, nsnull, PR_TRUE) &&
  2021)           SelectorMatchesTree(*aData, selector->mNext, PR_TRUE)) {
  2022)         *aResult = nsReStyleHint(*aResult | possibleChange);
                ^ 147 
  2023)       }
  2024)     }
  2025)   }
  2026)   return NS_OK;
          ^ 1,821 
  2027) }
  2028) 
  2029) struct AttributeEnumData {
  2030)   AttributeEnumData(AttributeRuleProcessorData *aData)
          ^ 34,833 
  2031)     : data(aData), change(nsReStyleHint(0)) {}
  2032) 
  2033)   AttributeRuleProcessorData *data;
  2034)   nsReStyleHint change;
  2035) };
  2036) 
  2037) 
  2038) static void
  2039) AttributeEnumFunc(nsCSSSelector* aSelector, AttributeEnumData* aData)
        ^ 12,074,413 
  2040) {
  2041)   AttributeRuleProcessorData *data = aData->data;
  2042) 
  2043)   nsReStyleHint possibleChange = IsSiblingOperator(aSelector->mOperator) ?
                                       ^ 48,297,596 (6)
  2044)     eReStyle_LaterSiblings : 
  2045)     (aSelector->mIsNextOfSomething ? eReStyle_Subtree : eReStyle_Self);
  2046) 
  2047)   // If enumData->change already includes all the bits of possibleChange, don't
  2048)   // bother calling SelectorMatches, since even if it returns false
  2049)   // enumData->change won't change.
  2050)   if ((possibleChange & ~(aData->change)) &&
          ^ 5,004,874 (4)
  2051)       SelectorMatches(*data, aSelector, data->mStateMask, data->mAttribute,
  2052)                       PR_TRUE) &&
  2053)       SelectorMatchesTree(*data, aSelector->mNext, PR_TRUE)) {
  2054)     aData->change = nsReStyleHint(aData->change | possibleChange);
            ^ 12,259 
  2055)   }
  2056) }
        ^ 12,074,413 
  2057) 
  2058) NS_IMETHODIMP
  2059) nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
                            ^ 34,833 
  2060)                                                nsReStyleHint* aResult)
  2061) {
  2062)   NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT),
          ^ 34,833 
  2063)                   "content must be element");
  2064) 
  2065)   AttributeEnumData data(aData);
                            ^ 34,833 
  2066) 
  2067)   // Since we always have :-moz-any-link (and almost always have :link
  2068)   // and :visited rules from prefs), rather than hacking AddRule below
  2069)   // to add |href| to the hash, we'll just handle it here.
  2070)   if (aData->mAttribute == nsGkAtoms::href &&
          ^ 34,839 (3/5)
  2071)       aData->mIsHTMLContent &&
  2072)       (aData->mContentTag == nsGkAtoms::a ||
  2073)        aData->mContentTag == nsGkAtoms::area ||
  2074)        aData->mContentTag == nsGkAtoms::link)) {
  2075)     data.change = nsReStyleHint(data.change | eReStyle_Self);
            ^ 3 
  2076)   }
  2077)   // XXX What about XLinks?
  2078) #ifdef MOZ_SVG
  2079)   // XXX should really check the attribute namespace is XLink
  2080)   if (aData->mAttribute == nsGkAtoms::href &&
          ^ 34,836 (2/3)
  2081)       aData->mNameSpaceID == kNameSpaceID_SVG &&
  2082)       aData->mContentTag == nsGkAtoms::a) {
  2083)     data.change = nsReStyleHint(data.change | eReStyle_Self);
            ^ 0 
  2084)   }
  2085) #endif
  2086)   // XXXbz now that :link and :visited are also states, do we need a
  2087)   // similar optimization in HasStateDependentStyle?
  2088) 
  2089)   RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
                                   ^ 69,666 (2)
  2090) 
  2091)   // We do the same thing for attributes that we do for state selectors
  2092)   // (see HasStateDependentStyle), except that instead of one big list
  2093)   // we have a hashtable with a per-attribute list.
  2094) 
  2095)   if (cascade) {
  2096)     if (aData->mAttribute == aData->mContent->GetIDAttributeName()) {
            ^ 69,666 (2)
  2097)       nsCSSSelector **iter = cascade->mIDSelectors.Elements(),
                                   ^ 420 (2)
  2098)                     **end = iter + cascade->mIDSelectors.Length();
                                  ^ 210 
  2099)       for(; iter != end; ++iter) {
              ^ 8,672 (2)
  2100)         AttributeEnumFunc(*iter, &data);
                ^ 8,462 
  2101)       }
  2102)     }
  2103)     
  2104)     if (aData->mAttribute == aData->mContent->GetClassAttributeName()) {
            ^ 69,666 (2)
  2105)       nsCSSSelector **iter = cascade->mClassSelectors.Elements(),
                                   ^ 30,856 (2)
  2106)                     **end = iter + cascade->mClassSelectors.Length();
                                  ^ 15,428 
  2107)       for(; iter != end; ++iter) {
              ^ 11,968,956 (2)
  2108)         AttributeEnumFunc(*iter, &data);
                ^ 11,953,528 
  2109)       }
  2110)     }
  2111) 
  2112)     AttributeSelectorEntry *entry = static_cast<AttributeSelectorEntry*>
                                          ^ 69,666 (2)
  2113)                                                (PL_DHashTableOperate(&cascade->mAttributeSelectors, aData->mAttribute,
  2114)                              PL_DHASH_LOOKUP));
  2115)     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
  2116)       nsCSSSelector **iter = entry->mSelectors->Elements(),
                                   ^ 7,924 (2)
  2117)                     **end = iter + entry->mSelectors->Length();
                                  ^ 3,962 
  2118)       for(; iter != end; ++iter) {
              ^ 116,385 (2)
  2119)         AttributeEnumFunc(*iter, &data);
                ^ 112,423 
  2120)       }
  2121)     }
  2122)   }
  2123) 
  2124)   *aResult = data.change;
          ^ 34,833 
  2125)   return NS_OK;
  2126) }
  2127) 
  2128) NS_IMETHODIMP
  2129) nsCSSRuleProcessor::MediumFeaturesChanged(nsPresContext* aPresContext,
                            ^ 91 
  2130)                                           PRBool* aRulesChanged)
  2131) {
  2132)   RuleCascadeData *old = mRuleCascades;
  2133)   // We don't want to do anything if there aren't any sets of rules
  2134)   // cached yet (or somebody cleared them and is thus responsible for
  2135)   // rebuilding things), since we should not build the rule cascade too
  2136)   // early (e.g., before we know whether the quirk style sheet should be
  2137)   // enabled).  And if there's nothing cached, it doesn't matter if
  2138)   // anything changed.  See bug 448281.
  2139)   if (old) {
  2140)     RefreshRuleCascade(aPresContext);
            ^ 91 
  2141)   }
  2142)   *aRulesChanged = (old != mRuleCascades);
          ^ 182 (2/3)
  2143)   return NS_OK;
          ^ 91 
  2144) }
  2145) 
  2146) // Append all the currently-active font face rules to aArray.  Return
  2147) // true for success and false for failure.
  2148) PRBool
  2149) nsCSSRuleProcessor::AppendFontFaceRules(
                            ^ 142 
  2150)                               nsPresContext *aPresContext,
  2151)                               nsTArray<nsFontFaceRuleContainer>& aArray)
  2152) {
  2153)   RuleCascadeData* cascade = GetRuleCascade(aPresContext);
                                   ^ 142 
  2154) 
  2155)   if (cascade) {
  2156)     if (!aArray.AppendElements(cascade->mFontFaceRules))
            ^ 284 (2)
  2157)       return PR_FALSE;
              ^ 0 
  2158)   }
  2159)   
  2160)   return PR_TRUE;
          ^ 142 
  2161) }
  2162) 
  2163) nsresult
  2164) nsCSSRuleProcessor::ClearRuleCascades()
                            ^ 168 
  2165) {
  2166)   // We rely on our caller (perhaps indirectly) to do something that
  2167)   // will rebuild style data and the user font set (either
  2168)   // nsIPresShell::ReconstructStyleData or
  2169)   // nsPresContext::RebuildAllStyleData).
  2170)   RuleCascadeData *data = mRuleCascades;
  2171)   mRuleCascades = nsnull;
  2172)   while (data) {
          ^ 290 (2)
  2173)     RuleCascadeData *next = data->mNext;
                                  ^ 122 
  2174)     delete data;
            ^ 122 
  2175)     data = next;
  2176)   }
  2177)   return NS_OK;
          ^ 168 
  2178) }
  2179) 
  2180) 
  2181) // This function should return true only for selectors that need to be
  2182) // checked by |HasStateDependentStyle|.
  2183) inline
  2184) PRBool IsStateSelector(nsCSSSelector& aSelector)
               ^ 56,148 
  2185) {
  2186)   for (nsPseudoClassList* pseudoClass = aSelector.mPseudoClassList;
          ^ 64,883 (2)
  2187)        pseudoClass; pseudoClass = pseudoClass->mNext) {
  2188)     if ((pseudoClass->mAtom == nsCSSPseudoClasses::active) ||
            ^ 487,054 (50)
  2189)         (pseudoClass->mAtom == nsCSSPseudoClasses::checked) ||
  2190)         (pseudoClass->mAtom == nsCSSPseudoClasses::mozDragOver) || 
  2191)         (pseudoClass->mAtom == nsCSSPseudoClasses::focus) || 
  2192)         (pseudoClass->mAtom == nsCSSPseudoClasses::hover) ||
  2193)         (pseudoClass->mAtom == nsCSSPseudoClasses::target) ||
  2194)         (pseudoClass->mAtom == nsCSSPseudoClasses::link) ||
  2195)         (pseudoClass->mAtom == nsCSSPseudoClasses::visited) ||
  2196)         (pseudoClass->mAtom == nsCSSPseudoClasses::enabled) ||
  2197)         (pseudoClass->mAtom == nsCSSPseudoClasses::disabled) ||
  2198)         (pseudoClass->mAtom == nsCSSPseudoClasses::mozBroken) ||
  2199)         (pseudoClass->mAtom == nsCSSPseudoClasses::mozUserDisabled) ||
  2200)         (pseudoClass->mAtom == nsCSSPseudoClasses::mozSuppressed) ||
  2201)   (pseudoClass->mAtom == nsCSSPseudoClasses::mozLoading) ||
  2202)         (pseudoClass->mAtom == nsCSSPseudoClasses::required) ||
  2203)         (pseudoClass->mAtom == nsCSSPseudoClasses::optional) ||
  2204)         (pseudoClass->mAtom == nsCSSPseudoClasses::valid) ||
  2205)         (pseudoClass->mAtom == nsCSSPseudoClasses::invalid) ||
  2206)         (pseudoClass->mAtom == nsCSSPseudoClasses::inRange) ||
  2207)         (pseudoClass->mAtom == nsCSSPseudoClasses::outOfRange) ||
  2208)         (pseudoClass->mAtom == nsCSSPseudoClasses::mozReadOnly) ||
  2209)         (pseudoClass->mAtom == nsCSSPseudoClasses::mozReadWrite) ||
  2210)         (pseudoClass->mAtom == nsCSSPseudoClasses::indeterminate) ||
  2211) #ifdef MOZ_MATHML
  2212)         (pseudoClass->mAtom == nsCSSPseudoClasses::mozMathIncrementScriptLevel) ||
  2213) #endif
  2214)         (pseudoClass->mAtom == nsCSSPseudoClasses::defaultPseudo)) {
  2215)       return PR_TRUE;
              ^ 4,844 
  2216)     }
  2217)   }
  2218)   return PR_FALSE;
          ^ 51,304 
  2219) }
  2220) 
  2221) static PRBool
  2222) AddRule(RuleValue* aRuleInfo, void* aCascade)
        ^ 39,013 
  2223) {
  2224)   RuleCascadeData *cascade = static_cast<RuleCascadeData*>(aCascade);
  2225) 
  2226)   // Build the rule hash.
  2227)   cascade->mRuleHash.PrependRule(aRuleInfo);
  2228) 
  2229)   nsTArray<nsCSSSelector*>* stateArray = &cascade->mStateSelectors;
                                               ^ 39,013 
  2230)   nsTArray<nsCSSSelector*>* classArray = &cascade->mClassSelectors;
  2231)   nsTArray<nsCSSSelector*>* idArray = &cascade->mIDSelectors;
  2232)   
  2233)   for (nsCSSSelector* selector = aRuleInfo->mSelector;
          ^ 94,458 (2)
  2234)            selector; selector = selector->mNext) {
  2235)     // It's worth noting that this loop over negations isn't quite
  2236)     // optimal for two reasons.  One, we could add something to one of
  2237)     // these lists twice, which means we'll check it twice, but I don't
  2238)     // think that's worth worrying about.   (We do the same for multiple
  2239)     // attribute selectors on the same attribute.)  Two, we don't really
  2240)     // need to check negations past the first in the current
  2241)     // implementation (and they're rare as well), but that might change
  2242)     // in the future if :not() is extended. 
  2243)     for (nsCSSSelector* negation = selector; negation;
            ^ 111,593 (2)                ^ 55,445 
  2244)          negation = negation->mNegations) {
  2245)       // Build mStateSelectors.
  2246)       if (IsStateSelector(*negation))
              ^ 112,296 (2)
  2247)         stateArray->AppendElement(selector);
                ^ 4,844 
  2248) 
  2249)       // Build mIDSelectors
  2250)       if (negation->mIDList) {
              ^ 56,148 
  2251)         idArray->AppendElement(selector);
                ^ 1,370 
  2252)       }
  2253)       
  2254)       // Build mClassSelectors
  2255)       if (negation->mClassList) {
              ^ 56,148 
  2256)         classArray->AppendElement(selector);
                ^ 9,653 
  2257)       }
  2258) 
  2259)       // Build mAttributeSelectors.
  2260)       for (nsAttrSelector *attr = negation->mAttrList; attr;
              ^ 65,014 (2)              ^ 56,148 
  2261)            attr = attr->mNext) {
  2262)         nsTArray<nsCSSSelector*> *array = cascade->AttributeListFor(attr->mAttr);
                                                ^ 26,598 (3)
  2263)         if (!array)
  2264)           return PR_FALSE;
                  ^ 0 
  2265)         array->AppendElement(selector);
                ^ 8,866 
  2266)       }
  2267)     }
  2268)   }
  2269) 
  2270)   return PR_TRUE;
          ^ 39,013 
  2271) }
  2272) 
  2273) struct PerWeightData {
  2274)   PRInt32 mWeight;
  2275)   RuleValue* mRules; // linked list (reverse order)
  2276) };
  2277) 
  2278) struct RuleByWeightEntry : public PLDHashEntryHdr {
  2279)   PerWeightData data; // mWeight is key, mRules are value
  2280) };
  2281) 
  2282) static PLDHashNumber
  2283) HashIntKey(PLDHashTable *table, const void *key)
        ^ 39,013 
  2284) {
  2285)   return PLDHashNumber(NS_PTR_TO_INT32(key));
  2286) }
  2287) 
  2288) static PRBool
  2289) MatchWeightEntry(PLDHashTable *table, const PLDHashEntryHdr *hdr,
        ^ 38,011 
  2290)                  const void *key)
  2291) {
  2292)   const RuleByWeightEntry *entry = (const RuleByWeightEntry *)hdr;
  2293)   return entry->data.mWeight == NS_PTR_TO_INT32(key);
  2294) }
  2295) 
  2296) static PLDHashTableOps gRulesByWeightOps = {
  2297)     PL_DHashAllocTable,
  2298)     PL_DHashFreeTable,
  2299)     HashIntKey,
  2300)     MatchWeightEntry,
  2301)     PL_DHashMoveEntryStub,
  2302)     PL_DHashClearEntryStub,
  2303)     PL_DHashFinalizeStub,
  2304)     NULL
  2305) };
  2306) 
  2307) struct CascadeEnumData {
  2308)   CascadeEnumData(nsPresContext* aPresContext,
          ^ 122 
  2309)                   nsTArray<nsFontFaceRuleContainer>& aFontFaceRules,
  2310)                   nsMediaQueryResultCacheKey& aKey,
  2311)                   PLArenaPool& aArena,
  2312)                   PRUint8 aSheetType)
  2313)     : mPresContext(aPresContext),
  2314)       mFontFaceRules(aFontFaceRules),
  2315)       mCacheKey(aKey),
  2316)       mArena(aArena),
  2317)       mSheetType(aSheetType)
  2318)   {
  2319)     if (!PL_DHashTableInit(&mRulesByWeight, &gRulesByWeightOps, nsnull,
            ^ 122 
  2320)                           sizeof(RuleByWeightEntry), 64))
  2321)       mRulesByWeight.ops = nsnull;
              ^ 0 
  2322)   }
          ^ 122 
  2323) 
  2324)   ~CascadeEnumData()
          ^ 122 
  2325)   {
  2326)     if (mRulesByWeight.ops)
  2327)       PL_DHashTableFinish(&mRulesByWeight);
              ^ 122 
  2328)   }
          ^ 122 
  2329) 
  2330)   nsPresContext* mPresContext;
  2331)   nsTArray<nsFontFaceRuleContainer>& mFontFaceRules;
  2332)   nsMediaQueryResultCacheKey& mCacheKey;
  2333)   PLArenaPool& mArena;
  2334)   // Hooray, a manual PLDHashTable since nsClassHashtable doesn't
  2335)   // provide a getter that gives me a *reference* to the value.
  2336)   PLDHashTable mRulesByWeight; // of RuleValue* linked lists (?)
  2337)   PRUint8 mSheetType;
  2338) };
  2339) 
  2340) /*
  2341)  * This enumerates style rules in a sheet (and recursively into any
  2342)  * grouping rules) in order to:
  2343)  *  (1) add any style rules, in order, into data->mRulesByWeight (for
  2344)  *      the primary CSS cascade), where they are separated by weight
  2345)  *      but kept in order per-weight, and
  2346)  *  (2) add any @font-face rules, in order, into data->mFontFaceRules.
  2347)  */
  2348) static PRBool
  2349) CascadeRuleEnumFunc(nsICSSRule* aRule, void* aData)
        ^ 21,262 
  2350) {
  2351)   CascadeEnumData* data = (CascadeEnumData*)aData;
  2352)   PRInt32 type = nsICSSRule::UNKNOWN_RULE;
  2353)   aRule->GetType(type);
  2354) 
  2355)   if (nsICSSRule::STYLE_RULE == type) {
          ^ 23,231 (4)
  2356)     nsICSSStyleRule* styleRule = (nsICSSStyleRule*)aRule;
                                       ^ 20,558 
  2357) 
  2358)     for (nsCSSSelectorList *sel = styleRule->Selector();
            ^ 59,571 (2)                ^ 20,558 
  2359)          sel; sel = sel->mNext) {
  2360)       PRInt32 weight = sel->mWeight;
                             ^ 39,013 
  2361)       RuleByWeightEntry *entry = static_cast<RuleByWeightEntry*>(
                                       ^ 39,013 
  2362)         PL_DHashTableOperate(&data->mRulesByWeight, NS_INT32_TO_PTR(weight),
  2363)                              PL_DHASH_ADD));
  2364)       if (!entry)
  2365)         return PR_FALSE;
                ^ 0 
  2366)       entry->data.mWeight = weight;
              ^ 39,013 
  2367)       RuleValue *info =
                              ^ 117,039 (3/4)
  2368)         new (data->mArena) RuleValue(styleRule, sel->mSelectors);
  2369)       // entry->data.mRules must be in backwards order.
  2370)       info->mNext = entry->data.mRules;
  2371)       entry->data.mRules = info;
  2372)     }
  2373)   }
  2374)   else if (nsICSSRule::MEDIA_RULE == type ||
  2375)            nsICSSRule::DOCUMENT_RULE == type) {
  2376)     nsICSSGroupRule* groupRule = (nsICSSGroupRule*)aRule;
                                       ^ 143 
  2377)     if (groupRule->UseForPresentation(data->mPresContext, data->mCacheKey))
            ^ 143 
  2378)       if (!groupRule->EnumerateRulesForwards(CascadeRuleEnumFunc, aData))
              ^ 6 (2)
  2379)         return PR_FALSE;
                ^ 0 
  2380)   }
  2381)   else if (nsICSSRule::FONT_FACE_RULE == type) {
  2382)     nsCSSFontFaceRule *fontFaceRule = static_cast<nsCSSFontFaceRule*>(aRule);
                                            ^ 0 (4)
  2383)     nsFontFaceRuleContainer *ptr = data->mFontFaceRules.AppendElement();
                                         ^ 0 
  2384)     if (!ptr)
  2385)       return PR_FALSE;
              ^ 0 
  2386)     ptr->mRule = fontFaceRule;
            ^ 0 
  2387)     ptr->mSheetType = data->mSheetType;
            ^ 0 
  2388)   }
  2389) 
  2390)   return PR_TRUE;
          ^ 21,262 
  2391) }
  2392) 
  2393) /* static */ PRBool
  2394) nsCSSRuleProcessor::CascadeSheetEnumFunc(nsICSSStyleSheet* aSheet, void* aData)
                            ^ 353 
  2395) {
  2396)   nsCSSStyleSheet*  sheet = static_cast<nsCSSStyleSheet*>(aSheet);
  2397)   CascadeEnumData* data = static_cast<CascadeEnumData*>(aData);
  2398)   PRBool bSheetApplicable = PR_TRUE;
  2399)   sheet->GetApplicable(bSheetApplicable);
  2400) 
  2401)   if (bSheetApplicable &&
          ^ 1,400 (4)
  2402)       sheet->UseForPresentation(data->mPresContext, data->mCacheKey) &&
  2403)       sheet->mInner) {
  2404)     nsCSSStyleSheet* child = sheet->mInner->mFirstChild;
                                   ^ 698 (2)
  2405)     while (child) {
            ^ 424 (2)
  2406)       CascadeSheetEnumFunc(child, data);
              ^ 75 
  2407)       child = child->mNext;
              ^ 75 
  2408)     }
  2409) 
  2410)     if (!sheet->mInner->mOrderedRules.EnumerateForwards(CascadeRuleEnumFunc,
            ^ 698 (2)
  2411)                                                         data))
  2412)       return PR_FALSE;
              ^ 0 
  2413)   }
  2414)   return PR_TRUE;
          ^ 353 
  2415) }
  2416) 
  2417) static int CompareWeightData(const void* aArg1, const void* aArg2,
                   ^ 2,457 
  2418)                              void* closure)
  2419) {
  2420)   const PerWeightData* arg1 = static_cast<const PerWeightData*>(aArg1);
  2421)   const PerWeightData* arg2 = static_cast<const PerWeightData*>(aArg2);
  2422)   return arg1->mWeight - arg2->mWeight; // put lower weight first
  2423) }
  2424) 
  2425) 
  2426) struct FillWeightArrayData {
  2427)   FillWeightArrayData(PerWeightData* aArrayData) :
          ^ 122 
  2428)     mIndex(0),
  2429)     mWeightArray(aArrayData)
  2430)   {
  2431)   }
  2432)   PRInt32 mIndex;
  2433)   PerWeightData* mWeightArray;
  2434) };
  2435) 
  2436) 
  2437) static PLDHashOperator
  2438) FillWeightArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
        ^ 1,002 
  2439)                 PRUint32 number, void *arg)
  2440) {
  2441)   FillWeightArrayData* data = static_cast<FillWeightArrayData*>(arg);
  2442)   const RuleByWeightEntry *entry = (const RuleByWeightEntry *)hdr;
  2443) 
  2444)   data->mWeightArray[data->mIndex++] = entry->data;
  2445) 
  2446)   return PL_DHASH_NEXT;
  2447) }
  2448) 
  2449) RuleCascadeData*
  2450) nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext)
                            ^ 890,312 
  2451) {
  2452)   // If anything changes about the presentation context, we will be
  2453)   // notified.  Otherwise, our cache is valid if mLastPresContext
  2454)   // matches aPresContext.  (The only rule processors used for multiple
  2455)   // pres contexts are for XBL.  These rule processors are probably less
  2456)   // likely to have @media rules, and thus the cache is pretty likely to
  2457)   // hit instantly even when we're switching between pres contexts.)
  2458) 
  2459)   if (!mRuleCascades || aPresContext != mLastPresContext) {
          ^ 890,190 
  2460)     RefreshRuleCascade(aPresContext);
            ^ 261 
  2461)   }
  2462)   mLastPresContext = aPresContext;
          ^ 890,312 
  2463) 
  2464)   return mRuleCascades;
  2465) }
  2466) 
  2467) void
  2468) nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
                            ^ 352 
  2469) {
  2470)   // Having RuleCascadeData objects be per-medium (over all variation
  2471)   // caused by media queries, handled through mCacheKey) works for now
  2472)   // since nsCSSRuleProcessor objects are per-document.  (For a given
  2473)   // set of stylesheets they can vary based on medium (@media) or
  2474)   // document (@-moz-document).)
  2475) 
  2476)   for (RuleCascadeData **cascadep = &mRuleCascades, *cascade;
          ^ 352 (1/2)
  2477)        (cascade = *cascadep); cascadep = &cascade->mNext) {
  2478)     if (cascade->mCacheKey.Matches(aPresContext)) {
            ^ 460 (2)
  2479)       // Ensure that the current one is always mRuleCascades.
  2480)       *cascadep = cascade->mNext;
              ^ 230 
  2481)       cascade->mNext = mRuleCascades;
  2482)       mRuleCascades = cascade;
  2483) 
  2484)       return;
  2485)     }
  2486)   }
  2487) 
  2488)   if (mSheets.Count() != 0) {
          ^ 244 (2)
  2489)     nsAutoPtr<RuleCascadeData> newCascade(
                                       ^ 976 (8/9)
  2490)       new RuleCascadeData(aPresContext->Medium(),
  2491)                           eCompatibility_NavQuirks == aPresContext->CompatibilityMode()));
  2492)     if (newCascade) {
            ^ 244 (2)
  2493)       CascadeEnumData data(aPresContext, newCascade->mFontFaceRules,
                              ^ 610 (5)
  2494)                            newCascade->mCacheKey,
  2495)                            newCascade->mRuleHash.Arena(),
  2496)                            mSheetType);
  2497)       if (!data.mRulesByWeight.ops)
              ^ 122 
  2498)         return; /* out of memory */
                ^ 0 (3)
  2499)       if (!mSheets.EnumerateForwards(CascadeSheetEnumFunc, &data))
              ^ 244 (2)
  2500)         return; /* out of memory */
                ^ 0 (3)
  2501) 
  2502)       // Sort the hash table of per-weight linked lists by weight.
  2503)       PRUint32 weightCount = data.mRulesByWeight.entryCount;
                                   ^ 122 
  2504)       nsAutoArrayPtr<PerWeightData> weightArray(new PerWeightData[weightCount]);
                                            ^ 122 
  2505)       FillWeightArrayData fwData(weightArray);
                                  ^ 244 (2)
  2506)       PL_DHashTableEnumerate(&data.mRulesByWeight, FillWeightArray, &fwData);
              ^ 122 
  2507)       NS_QuickSort(weightArray, weightCount, sizeof(PerWeightData),
              ^ 244 (2)
  2508)                    CompareWeightData, nsnull);
  2509) 
  2510)       // Put things into the rule hash backwards because it's easier to
  2511)       // build a singly linked list lowest-first that way.
  2512)       // The primary sort is by weight...
  2513)       PRUint32 i = weightCount;
                         ^ 122 
  2514)       while (i > 0) {
              ^ 1,124 (2)
  2515)         --i;
                ^ 1,002 
  2516)         // and the secondary sort is by order.  mRules are already backwards.
  2517)         RuleValue *ruleValue = weightArray[i].mRules;
                                     ^ 1,002 
  2518)         do {
  2519)           // Calling |AddRule| reuses mNext!
  2520)           RuleValue *next = ruleValue->mNext;
                                  ^ 39,013 
  2521)           if (!AddRule(ruleValue, newCascade))
                  ^ 78,026 (2)
  2522)             return; /* out of memory */
                    ^ 0 (4)
  2523)           ruleValue = next;
                  ^ 39,013 
  2524)         } while (ruleValue);
  2525)       }
  2526) 
  2527)       // Ensure that the current one is always mRuleCascades.
  2528)       newCascade->mNext = mRuleCascades;
              ^ 244 (2)
  2529)       mRuleCascades = newCascade.forget();
              ^ 122 
  2530)     }
            ^ 122 
  2531)   }
          ^ 122 
  2532)   return;
          ^ 122 
  2533) }
  2534) 
  2535) /* static */ PRBool
  2536) nsCSSRuleProcessor::SelectorListMatches(RuleProcessorData& aData,
        ^ 0 
  2537)                                         nsCSSSelectorList* aSelectorList)
  2538) {
  2539)   while (aSelectorList) {
  2540)     nsCSSSelector* sel = aSelectorList->mSelectors;
  2541)     NS_ASSERTION(sel, "Should have *some* selectors");
  2542)     if (SelectorMatches(aData, sel, 0, nsnull, PR_FALSE)) {
  2543)       nsCSSSelector* next = sel->mNext;
  2544)       if (!next || SelectorMatchesTree(aData, next, PR_FALSE)) {
  2545)         return PR_TRUE;
  2546)       }
  2547)     }
  2548) 
  2549)     aSelectorList = aSelectorList->mNext;
  2550)   }
  2551) 
  2552)   return PR_FALSE;
  2553) }

generated by Intel® Compilers
code-coverage tool
Web-Page Owner: moh