if (result == localTrue && aSelector->mAttrList) {
if (result && aSelector->mAttrList) {
static PRBool SelectorMatches(SelectorMatchesData &data,                              nsCSSSelector* aSelector,                              PRBool aTestState,                              PRInt8 aNegationIndex) {  // if we are dealing with negations, reverse the values of PR_TRUE and PR_FALSE  PRBool  localFalse = PRBool(0 < aNegationIndex);  PRBool  localTrue = PRBool(0 == aNegationIndex);  PRBool  checkType = (0 == aNegationIndex) || (1 < aNegationIndex);  PRBool  result = localFalse;  // Bail out early if we can. Do not perform the test if aNegationIndex==1  // because it then contains only negated IDs, classes, attributes and pseudo-  // classes  if (checkType) {    if (kNameSpaceID_Unknown != aSelector->mNameSpace) {      if (data.mNameSpaceID != aSelector->mNameSpace) {        return result;      }    }  }    if (checkType) {    if ((nsnull != aSelector->mTag) && (aSelector->mTag != data.mContentTag))  {      return result;    }    if (1 < aNegationIndex) {      // optimization : no other selector to test on negated type or      // universal selector      return localTrue;    }  }  result = localTrue;    if ((localTrue == result) &&      (nsnull != aSelector->mPseudoClassList)) {  // test for pseudo class match    // first-child, root, lang, active, focus, hover, link, visited...    // XXX disabled, enabled, selected, selection    nsAtomList* pseudoClass = aSelector->mPseudoClassList;    while ((localTrue == result) && (nsnull != pseudoClass)) {      if ((nsCSSAtoms::firstChildPseudo == pseudoClass->mAtom) ||          (nsCSSAtoms::firstNodePseudo == pseudoClass->mAtom) ) {        nsIContent* firstChild = nsnull;        nsIContent* parent = data.mParentContent;        if (parent) {          PRInt32 index = -1;          do {            parent->ChildAt(++index, firstChild);            if (firstChild) { // stop at first non-comment and non-whitespace node (and non-text node for firstChild)              if (IsSignificantChild(firstChild, (nsCSSAtoms::firstNodePseudo == pseudoClass->mAtom))) {                break;              }              NS_RELEASE(firstChild);            }            else {              break;            }          } while (1 == 1);        }        result = PRBool(localTrue == (data.mContent == firstChild));        NS_IF_RELEASE(firstChild);      }      else if ((nsCSSAtoms::lastChildPseudo == pseudoClass->mAtom) ||               (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom)) {        nsIContent* lastChild = nsnull;        nsIContent* parent = data.mParentContent;        if (parent) {          PRInt32 index;          parent->ChildCount(index);          do {            parent->ChildAt(--index, lastChild);            if (lastChild) { // stop at first non-comment and non-whitespace node (and non-text node for lastChild)              if (IsSignificantChild(lastChild, (nsCSSAtoms::lastNodePseudo == pseudoClass->mAtom))) {                break;              }              NS_RELEASE(lastChild);            }            else {              break;            }          } while (1 == 1);        }        result = PRBool(localTrue == (data.mContent == lastChild));        NS_IF_RELEASE(lastChild);      }      else if (nsCSSAtoms::rootPseudo == pseudoClass->mAtom) {        if (data.mParentContent) {          result = localFalse;        }        else {          result = localTrue;        }      }      else if (nsCSSAtoms::xblBoundElementPseudo == pseudoClass->mAtom) {        if (!data.mStyleRuleSupplier) {          nsCOMPtr<nsIPresShell> shell;          data.mPresContext->GetShell(getter_AddRefs(shell));          nsCOMPtr<nsIStyleSet> styleSet;          shell->GetStyleSet(getter_AddRefs(styleSet));          styleSet->GetStyleRuleSupplier(getter_AddRefs(data.mStyleRuleSupplier));        }        if (data.mStyleRuleSupplier)          data.mStyleRuleSupplier->MatchesScopedRoot(data.mContent, &result);        else           result = localFalse;      }      else if (nsCSSAtoms::langPseudo == pseudoClass->mAtom) {        // XXX not yet implemented        result = localFalse;      }      else if (IsEventPseudo(pseudoClass->mAtom)) {        // check if the element is event-sensitive        // Quirk Mode: check to see if the element is event-sensitive        //  - see if the selector applies to event pseudo classes        // NOTE: we distinguish between global and subjected selectors so        //       pass that information on to the determining routine        PRBool isSelectorGlobal = aSelector->mTag==nsnull ? PR_TRUE : PR_FALSE;        if ((data.mIsQuirkMode) &&            (!IsEventSensitive(pseudoClass->mAtom, data.mContentTag, isSelectorGlobal))){          result = localFalse;        } else if (aTestState) {          if (nsCSSAtoms::activePseudo == pseudoClass->mAtom) {            result = PRBool(localTrue == (0 != (data.mEventState & NS_EVENT_STATE_ACTIVE)));          }          else if (nsCSSAtoms::focusPseudo == pseudoClass->mAtom) {            result = PRBool(localTrue == (0 != (data.mEventState & NS_EVENT_STATE_FOCUS)));          }          else if (nsCSSAtoms::hoverPseudo == pseudoClass->mAtom) {            result = PRBool(localTrue == (0 != (data.mEventState & NS_EVENT_STATE_HOVER)));          }          else if (nsCSSAtoms::dragOverPseudo == pseudoClass->mAtom) {            result = PRBool(localTrue == (0 != (data.mEventState & NS_EVENT_STATE_DRAGOVER)));          }        }       }      else if (IsLinkPseudo(pseudoClass->mAtom)) {        if (data.mIsHTMLLink || data.mIsSimpleXLink) {          if ((localFalse != result) && (aTestState)) {            if (nsCSSAtoms::linkPseudo == pseudoClass->mAtom) {              result = PRBool(localTrue == (eLinkState_Unvisited == data.mLinkState));            }            else if (nsCSSAtoms::visitedPseudo == pseudoClass->mAtom) {              result = PRBool(localTrue == (eLinkState_Visited == data.mLinkState));            }          }        }        else {          result = localFalse;  // not a link        }      }      else {        result = localFalse;  // unknown pseudo class      }      pseudoClass = pseudoClass->mNext;    }  }  // namespace/tag match  if (result == localTrue && aSelector->mAttrList) { // test for attribute match    // if no attributes on the content, no match    if(!data.mHasAttributes) {      result = localFalse;    } else {      nsAttrSelector* attr = aSelector->mAttrList;      do {        nsAutoString  value, partValue;        nsresult  attrState = data.mContent->GetAttribute(attr->mNameSpace, attr->mAttr, value);        if (NS_FAILED(attrState) || (NS_CONTENT_ATTR_NOT_THERE == attrState)) {          result = localFalse;        }        else {          PRBool isCaseSensitive = (attr->mCaseSensitive && !data.mIsHTMLContent); // Bug 24390: html attributes should not be case-sensitive          switch (attr->mFunction) {            case NS_ATTR_FUNC_SET:    break;            case NS_ATTR_FUNC_EQUALS:               if (isCaseSensitive) {                result = PRBool(localTrue == value.Equals(attr->mValue));              }              else {                result = PRBool(localTrue == value.EqualsIgnoreCase(attr->mValue));              }              break;            case NS_ATTR_FUNC_INCLUDES:               result = PRBool(localTrue == ValueIncludes(value, attr->mValue, isCaseSensitive));              break;            case NS_ATTR_FUNC_DASHMATCH:               result = PRBool(localTrue == ValueDashMatch(value, attr->mValue, isCaseSensitive));              break;            case NS_ATTR_FUNC_ENDSMATCH:              value.Right(partValue, attr->mValue.Length());              if (isCaseSensitive) {                result = PRBool(localTrue == partValue.Equals(attr->mValue));              }              else {                result = PRBool(localTrue == partValue.EqualsIgnoreCase(attr->mValue));              }              break;            case NS_ATTR_FUNC_BEGINSMATCH:              value.Left(partValue, attr->mValue.Length());              if (isCaseSensitive) {                result = PRBool(localTrue == partValue.Equals(attr->mValue));              }              else {                result = PRBool(localTrue == partValue.EqualsIgnoreCase(attr->mValue));              }              break;            case NS_ATTR_FUNC_CONTAINSMATCH:              result = PRBool(localTrue == (-1 != value.Find(attr->mValue, isCaseSensitive)));              break;          }        }        attr = attr->mNext;      } while ((localTrue == result) && (nsnull != attr));    }  }  if ((localTrue == result) &&      ((nsnull != aSelector->mIDList) || (nsnull != aSelector->mClassList))) {  // test for ID & class match    result = localFalse;    if (data.mStyledContent) {      nsAtomList* IDList = aSelector->mIDList;      if (nsnull == IDList) {        result = localTrue;      }      else if (nsnull != data.mContentID) {        result = localTrue;        while (nsnull != IDList) {          if (IDList->mAtom != data.mContentID) {            result = localFalse;            break;          }          IDList = IDList->mNext;        }      }            if (localTrue == result) {        nsAtomList* classList = aSelector->mClassList;        while (nsnull != classList) {          if (NS_COMFALSE == data.mStyledContent->HasClass(classList->mAtom)) {            result = localFalse;            break;          }          classList = classList->mNext;        }      }    }  }    // apply SelectorMatches to the negated selectors in the chain  if ((localTrue == result) && (nsnull != aSelector->mNegations)) {    result = SelectorMatches(data, aSelector->mNegations, aTestState, aNegationIndex+1);  }  return result;}