Backing out bug 525608 and bug 525952
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 10 Dec 2009 18:28:08 -0800
changeset 35549 813718244b94428e0c1a7e8f8d0de9973ccbfe4e
parent 35548 cb2351209fffa1676bed302e8f8406a3856bf362
child 35550 0eb81cc80d6ec2b1af72492cc265e7ed37730d78
push id10633
push userbzbarsky@mozilla.com
push dateFri, 11 Dec 2009 02:28:19 +0000
treeherdermozilla-central@813718244b94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs525608, 525952
milestone1.9.3a1pre
Backing out bug 525608 and bug 525952
content/base/src/nsGenericElement.cpp
content/canvas/src/nsCanvasRenderingContext2D.cpp
content/xbl/src/nsBindingManager.cpp
dom/locales/en-US/chrome/layout/css.properties
layout/base/nsCSSFrameConstructor.cpp
layout/base/nsCSSFrameConstructor.h
layout/base/nsFrameManager.cpp
layout/base/nsLayoutUtils.h
layout/forms/nsButtonFrameRenderer.cpp
layout/forms/nsComboboxControlFrame.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsBlockFrame.h
layout/generic/nsFrameSetFrame.cpp
layout/generic/nsInlineFrame.cpp
layout/generic/nsTextFrameThebes.cpp
layout/mathml/mathml.css
layout/mathml/nsMathMLFrame.cpp
layout/style/forms.css
layout/style/nsCSSAnonBoxList.h
layout/style/nsCSSParser.cpp
layout/style/nsCSSPseudoClassList.h
layout/style/nsCSSPseudoClasses.cpp
layout/style/nsCSSPseudoClasses.h
layout/style/nsCSSPseudoElementList.h
layout/style/nsCSSPseudoElements.cpp
layout/style/nsCSSPseudoElements.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSRuleProcessor.h
layout/style/nsCSSStyleRule.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsHTMLCSSStyleSheet.cpp
layout/style/nsHTMLStyleSheet.cpp
layout/style/nsHTMLStyleSheet.h
layout/style/nsICSSStyleRule.h
layout/style/nsIStyleRuleProcessor.h
layout/style/nsRuleProcessorData.h
layout/style/nsStyleAnimation.cpp
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
layout/style/nsStyleStruct.h
layout/style/nsTransitionManager.cpp
layout/style/nsTransitionManager.h
layout/style/test/Makefile.in
layout/style/test/test_bug525952.html
layout/tables/nsTableFrame.cpp
layout/xul/base/src/tree/src/nsTreeStyleCache.cpp
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -5135,55 +5135,38 @@ nsGenericElement::PostHandleEventForLink
 
 void
 nsGenericElement::GetLinkTarget(nsAString& aTarget)
 {
   aTarget.Truncate();
 }
 
 // NOTE: The aPresContext pointer is NOT addrefed.
-// *aSelectorList might be null even if NS_OK is returned; this
-// happens when all the selectors were pseudo-element selectors.
 static nsresult
 ParseSelectorList(nsINode* aNode,
                   const nsAString& aSelectorString,
                   nsCSSSelectorList** aSelectorList,
                   nsPresContext** aPresContext)
 {
   NS_ENSURE_ARG(aNode);
 
   nsIDocument* doc = aNode->GetOwnerDoc();
   NS_ENSURE_STATE(doc);
 
   nsCOMPtr<nsICSSParser> parser;
   nsresult rv = doc->CSSLoader()->GetParserFor(nsnull, getter_AddRefs(parser));
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCSSSelectorList* selectorList;
   rv = parser->ParseSelectorString(aSelectorString,
                                    doc->GetDocumentURI(),
                                    0, // XXXbz get the right line number!
-                                   &selectorList);
+                                   aSelectorList);
   doc->CSSLoader()->RecycleParser(parser);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  // Filter out pseudo-element selectors from selectorList
-  nsCSSSelectorList** slot = &selectorList;
-  do {
-    nsCSSSelectorList* cur = *slot;
-    if (cur->mSelectors->IsPseudoElement()) {
-      *slot = cur->mNext;
-      cur->mNext = nsnull;
-      delete cur;
-    } else {
-      slot = &cur->mNext;
-    }
-  } while (*slot);
-  *aSelectorList = selectorList;
-
   // It's not strictly necessary to have a prescontext here, but it's
   // a bit of an optimization for various stuff.
   *aPresContext = nsnull;
   nsIPresShell* shell = doc->GetPrimaryShell();
   if (shell) {
     *aPresContext = shell->GetPresContext();
   }
 
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -1940,29 +1940,25 @@ nsCanvasRenderingContext2D::SetFont(cons
         rv = CreateFontStyleRule(NS_LITERAL_STRING("10px sans-serif"),
                                  mCSSParser.get(),
                                  document,
                                  getter_AddRefs(parentRule));
         if (NS_FAILED(rv))
             return rv;
         nsCOMArray<nsIStyleRule> parentRules;
         parentRules.AppendObject(parentRule);
-        parentContext =
-            styleSet->ResolveStyleForRules(nsnull, nsnull,
-                                           nsCSSPseudoElements::ePseudo_NotPseudoElement,
-                                           nsnull, parentRules);
+        parentContext = styleSet->ResolveStyleForRules(nsnull, nsnull,
+                                                       nsnull, parentRules);
     }
 
     if (!parentContext)
         return NS_ERROR_FAILURE;
 
     nsRefPtr<nsStyleContext> sc =
-        styleSet->ResolveStyleForRules(parentContext, nsnull,
-                                       nsCSSPseudoElements::ePseudo_NotPseudoElement,
-                                       nsnull, rules);
+        styleSet->ResolveStyleForRules(parentContext, nsnull, nsnull, rules);
     if (!sc)
         return NS_ERROR_FAILURE;
     const nsStyleFont* fontStyle = sc->GetStyleFont();
 
     NS_ASSERTION(fontStyle, "Could not obtain font style");
 
     // use CSS pixels instead of dev pixels to avoid being affected by page zoom
     const PRUint32 aupcp = nsPresContext::AppUnitsPerCSSPixel();
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -1267,17 +1267,18 @@ nsBindingManager::GetBindingImplementati
 
 nsresult
 nsBindingManager::WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc,
                             RuleProcessorData* aData,
                             PRBool* aCutOffInheritance)
 {
   *aCutOffInheritance = PR_FALSE;
   
-  NS_ASSERTION(aData->mContent, "How did that happen?");
+  if (!aData->mContent)
+    return NS_OK;
 
   // Walk the binding scope chain, starting with the binding attached to our
   // content, up till we run out of scopes or we get cut off.
   nsIContent *content = aData->mContent;
   
   do {
     nsXBLBinding *binding = GetBinding(content);
     if (binding) {
--- a/dom/locales/en-US/chrome/layout/css.properties
+++ b/dom/locales/en-US/chrome/layout/css.properties
@@ -132,9 +132,8 @@ PEUnknownFontDesc=Unknown descriptor '%1
 PEMQExpectedExpressionStart=Expected '(' to start media query expression but found '%1$S'.
 PEMQExpressionEOF=contents of media query expression
 PEMQExpectedFeatureName=Expected media feature name but found '%1$S'.
 PEMQExpectedFeatureNameEnd=Expected ':' or ')' after media feature name but found '%1$S'.
 PEMQNoMinMaxWithoutValue=Media features with min- or max- must have a value.
 PEMQExpectedFeatureValue=Found invalid value for media feature.
 PEBadFontBlockStart=Expected '{' to begin @font-face rule but found '%1$S'.
 PEBadFontBlockEnd=Expected '}' to end @font-face rule but found '%1$S'.
-PEAnonBoxNotAlone=Did not expect anonymous box.
\ No newline at end of file
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -82,16 +82,17 @@
 #include "nsICheckboxControlFrame.h"
 #include "nsIDOMCharacterData.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsPlaceholderFrame.h"
 #include "nsTableRowGroupFrame.h"
 #include "nsStyleChangeList.h"
 #include "nsIFormControl.h"
 #include "nsCSSAnonBoxes.h"
+#include "nsCSSPseudoElements.h"
 #include "nsIDeviceContext.h"
 #include "nsTextFragment.h"
 #include "nsIAnonymousContentCreator.h"
 #include "nsFrameManager.h"
 #include "nsLegendFrame.h"
 #include "nsIContentIterator.h"
 #include "nsBoxLayoutState.h"
 #include "nsBindingManager.h"
@@ -1819,36 +1820,36 @@ nsCSSFrameConstructor::CreateGeneratedCo
  * aParentFrame/aParentContent, giving the XML element the ::before or
  * ::after style.
  */
 void
 nsCSSFrameConstructor::CreateGeneratedContentItem(nsFrameConstructorState& aState,
                                                   nsIFrame*        aParentFrame,
                                                   nsIContent*      aParentContent,
                                                   nsStyleContext*  aStyleContext,
-                                                  nsCSSPseudoElements::Type aPseudoElement,
+                                                  nsIAtom*         aPseudoElement,
                                                   FrameConstructionItemList& aItems)
 {
   // XXXbz is this ever true?
   if (!aParentContent->IsNodeOfType(nsINode::eELEMENT))
     return;
 
   nsStyleSet *styleSet = mPresShell->StyleSet();
 
   // Probe for the existence of the pseudo-element
   nsRefPtr<nsStyleContext> pseudoStyleContext;
-  pseudoStyleContext = styleSet->ProbePseudoElementStyle(aParentContent,
-                                                         aPseudoElement,
-                                                         aStyleContext);
+  pseudoStyleContext = styleSet->ProbePseudoStyleFor(aParentContent,
+                                                     aPseudoElement,
+                                                     aStyleContext);
   if (!pseudoStyleContext)
     return;
   // |ProbePseudoStyleFor| checked the 'display' property and the
   // |ContentCount()| of the 'content' property for us.
   nsCOMPtr<nsINodeInfo> nodeInfo;
-  nsIAtom* elemName = aPseudoElement == nsCSSPseudoElements::ePseudo_before ?
+  nsIAtom* elemName = aPseudoElement == nsCSSPseudoElements::before ?
     nsGkAtoms::mozgeneratedcontentbefore : nsGkAtoms::mozgeneratedcontentafter;
   nodeInfo = mDocument->NodeInfoManager()->GetNodeInfo(elemName, nsnull,
                                                        kNameSpaceID_None);
   nsCOMPtr<nsIContent> container;
   nsresult rv = NS_NewXMLElement(getter_AddRefs(container), nodeInfo);
   if (NS_FAILED(rv))
     return;
   container->SetNativeAnonymous();
@@ -2025,17 +2026,17 @@ nsCSSFrameConstructor::ConstructTable(ns
   nsStyleContext* const styleContext = aItem.mStyleContext;
   const PRUint32 nameSpaceID = aItem.mNameSpaceID;
   
   nsresult rv = NS_OK;
 
   // create the pseudo SC for the outer table as a child of the inner SC
   nsRefPtr<nsStyleContext> outerStyleContext;
   outerStyleContext = mPresShell->StyleSet()->
-    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::tableOuter, styleContext);
+    ResolvePseudoStyleFor(content, nsCSSAnonBoxes::tableOuter, styleContext);
 
   // Create the outer table frame which holds the caption and inner table frame
   nsIFrame* newFrame;
 #ifdef MOZ_MATHML
   if (kNameSpaceID_MathML == nameSpaceID)
     newFrame = NS_NewMathMLmtableOuterFrame(mPresShell, outerStyleContext);
   else
 #endif
@@ -2229,17 +2230,17 @@ nsCSSFrameConstructor::ConstructTableCel
 
   // Initialize the table cell frame
   InitAndRestoreFrame(aState, content, aParentFrame, nsnull, newFrame);
   nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE);
   
   // Resolve pseudo style and initialize the body cell frame
   nsRefPtr<nsStyleContext> innerPseudoStyle;
   innerPseudoStyle = mPresShell->StyleSet()->
-    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::cellContent, styleContext);
+    ResolvePseudoStyleFor(content, nsCSSAnonBoxes::cellContent, styleContext);
 
   // Create a block frame that will format the cell's content
   PRBool isBlock;
   nsIFrame* cellInnerFrame;
 #ifdef MOZ_MATHML
   if (kNameSpaceID_MathML == nameSpaceID) {
     cellInnerFrame = NS_NewMathMLmtdInnerFrame(mPresShell, innerPseudoStyle);
     isBlock = PR_FALSE;
@@ -2664,18 +2665,19 @@ nsCSSFrameConstructor::ConstructRootFram
   {
     styleSet->SetBindingManager(mDocument->BindingManager());
   }
 
   // --------- BUILD VIEWPORT -----------
   nsIFrame*                 viewportFrame = nsnull;
   nsRefPtr<nsStyleContext> viewportPseudoStyle;
 
-  viewportPseudoStyle =
-    styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::viewport, nsnull);
+  viewportPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
+                                                        nsCSSAnonBoxes::viewport,
+                                                        nsnull);
 
   viewportFrame = NS_NewViewportFrame(mPresShell, viewportPseudoStyle);
 
   // XXXbz do we _have_ to pass a null content pointer to that frame?
   // Would it really kill us to pass in the root element or something?
   // What would that break?
   viewportFrame->Init(nsnull, nsnull, nsnull);
 
@@ -2857,36 +2859,38 @@ nsCSSFrameConstructor::SetUpDocElementCo
   nsFrameConstructorState state(mPresShell, nsnull, nsnull, nsnull);
 
   // Start off with the viewport as parent; we'll adjust it as needed.
   nsIFrame* parentFrame = viewportFrame;
 
   nsStyleSet* styleSet = mPresShell->StyleSet();
   // If paginated, make sure we don't put scrollbars in
   if (!isScrollable) {
-    rootPseudoStyle = styleSet->ResolveAnonymousBoxStyle(rootPseudo,
-                                                         viewportPseudoStyle);
+    rootPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
+                                                      rootPseudo,
+                                                      viewportPseudoStyle);
   } else {
       if (rootPseudo == nsCSSAnonBoxes::canvas) {
         rootPseudo = nsCSSAnonBoxes::scrolledCanvas;
       } else {
         NS_ASSERTION(rootPseudo == nsCSSAnonBoxes::pageSequence,
                      "Unknown root pseudo");
         rootPseudo = nsCSSAnonBoxes::scrolledPageSequence;
       }
 
       // Build the frame. We give it the content we are wrapping which is the
       // document element, the root frame, the parent view port frame, and we
       // should get back the new frame and the scrollable view if one was
       // created.
 
       // resolve a context for the scrollframe
       nsRefPtr<nsStyleContext>  styleContext;
-      styleContext = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::viewportScroll,
-                                                        viewportPseudoStyle);
+      styleContext = styleSet->ResolvePseudoStyleFor(nsnull,
+                                                     nsCSSAnonBoxes::viewportScroll,
+                                                     viewportPseudoStyle);
 
       // Note that the viewport scrollframe is always built with
       // overflow:auto style. This forces the scroll frame to create
       // anonymous content for both scrollbars. This is necessary even
       // if the HTML or BODY elements are overriding the viewport
       // scroll style to 'hidden' --- dynamic style changes might put
       // scrollbars back on the viewport and we don't want to have to
       // reframe the viewport to create the scrollbar content.
@@ -2949,31 +2953,32 @@ nsCSSFrameConstructor::ConstructPageFram
                                           nsIFrame*      aPrevPageFrame,
                                           nsIFrame*&     aPageFrame,
                                           nsIFrame*&     aCanvasFrame)
 {
   nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext();
   nsStyleSet *styleSet = aPresShell->StyleSet();
 
   nsRefPtr<nsStyleContext> pagePseudoStyle;
-  pagePseudoStyle = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::page,
-                                                       parentStyleContext);
+  pagePseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
+                                                    nsCSSAnonBoxes::page,
+                                                    parentStyleContext);
 
   aPageFrame = NS_NewPageFrame(aPresShell, pagePseudoStyle);
   if (NS_UNLIKELY(!aPageFrame))
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Initialize the page frame and force it to have a view. This makes printing of
   // the pages easier and faster.
   aPageFrame->Init(nsnull, aParentFrame, aPrevPageFrame);
 
   nsRefPtr<nsStyleContext> pageContentPseudoStyle;
-  pageContentPseudoStyle =
-    styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::pageContent,
-                                       pagePseudoStyle);
+  pageContentPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
+                                                           nsCSSAnonBoxes::pageContent,
+                                                           pagePseudoStyle);
 
   nsIFrame* pageContentFrame = NS_NewPageContentFrame(aPresShell, pageContentPseudoStyle);
   if (NS_UNLIKELY(!pageContentFrame))
     return NS_ERROR_OUT_OF_MEMORY;
 
   // Initialize the page content frame and force it to have a view. Also make it the
   // containing block for fixed elements which are repeated on every page.
   nsIFrame* prevPageContentFrame = nsnull;
@@ -2981,18 +2986,19 @@ nsCSSFrameConstructor::ConstructPageFram
     prevPageContentFrame = aPrevPageFrame->GetFirstChild(nsnull);
     NS_ASSERTION(prevPageContentFrame, "missing page content frame");
   }
   pageContentFrame->Init(nsnull, aPageFrame, prevPageContentFrame);
   SetInitialSingleChild(aPageFrame, pageContentFrame);
   mFixedContainingBlock = pageContentFrame;
 
   nsRefPtr<nsStyleContext> canvasPseudoStyle;
-  canvasPseudoStyle = styleSet->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::canvas,
-                                                         pageContentPseudoStyle);
+  canvasPseudoStyle = styleSet->ResolvePseudoStyleFor(nsnull,
+                                                      nsCSSAnonBoxes::canvas,
+                                                      pageContentPseudoStyle);
 
   aCanvasFrame = NS_NewCanvasFrame(aPresShell, canvasPseudoStyle);
   if (NS_UNLIKELY(!aCanvasFrame))
     return NS_ERROR_OUT_OF_MEMORY;
 
   nsIFrame* prevCanvasFrame = nsnull;
   if (prevPageContentFrame) {
     prevCanvasFrame = prevPageContentFrame->GetFirstChild(nsnull);
@@ -3073,18 +3079,19 @@ nsCSSFrameConstructor::ConstructButtonFr
     buttonFrame->Destroy();
     return rv;
   }
   // See if we need to create a view
   nsHTMLContainerFrame::CreateViewForFrame(buttonFrame, PR_FALSE);
 
   nsRefPtr<nsStyleContext> innerBlockContext;
   innerBlockContext =
-    mPresShell->StyleSet()->ResolveAnonymousBoxStyle(nsCSSAnonBoxes::buttonContent,
-                                                     styleContext);
+    mPresShell->StyleSet()->ResolvePseudoStyleFor(content,
+                                                  nsCSSAnonBoxes::buttonContent,
+                                                  styleContext);
                                                                
   nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, innerBlockContext,
                                           NS_BLOCK_FLOAT_MGR);
 
   if (NS_UNLIKELY(!blockFrame)) {
     buttonFrame->Destroy();
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -3212,18 +3219,19 @@ nsCSSFrameConstructor::ConstructSelectFr
       // Combobox - Old Native Implementation
       ///////////////////////////////////////////////////////////////////
       nsIComboboxControlFrame* comboBox = do_QueryFrame(comboboxFrame);
       NS_ASSERTION(comboBox, "NS_NewComboboxControlFrame returned frame that "
                              "doesn't implement nsIComboboxControlFrame");
 
         // Resolve pseudo element style for the dropdown list
       nsRefPtr<nsStyleContext> listStyle;
-      listStyle = mPresShell->StyleSet()->
-        ResolveAnonymousBoxStyle(nsCSSAnonBoxes::dropDownList, styleContext);
+      listStyle = mPresShell->StyleSet()->ResolvePseudoStyleFor(content,
+                                                                nsCSSAnonBoxes::dropDownList, 
+                                                                styleContext);
 
         // Create a listbox
       nsIFrame* listFrame = NS_NewListControlFrame(mPresShell, listStyle);
 
         // Notify the listbox that it is being used as a dropdown list.
       nsIListControlFrame * listControlFrame = do_QueryFrame(listFrame);
       if (listControlFrame) {
         listControlFrame->SetComboboxFrame(comboboxFrame);
@@ -3409,18 +3417,20 @@ nsCSSFrameConstructor::ConstructFieldSet
                       nsnull, newFrame);
 
   // See if we need to create a view, e.g. the frame is absolutely
   // positioned
   nsHTMLContainerFrame::CreateViewForFrame(newFrame, PR_FALSE);
 
   // Resolve style and initialize the frame
   nsRefPtr<nsStyleContext> fieldsetContentStyle;
-  fieldsetContentStyle = mPresShell->StyleSet()->
-    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::fieldsetContent, styleContext);
+  fieldsetContentStyle =
+    mPresShell->StyleSet()->ResolvePseudoStyleFor(content,
+                                                  nsCSSAnonBoxes::fieldsetContent,
+                                                  styleContext);
 
   nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, fieldsetContentStyle,
                                           NS_BLOCK_FLOAT_MGR |
                                           NS_BLOCK_MARGIN_ROOT);
   InitAndRestoreFrame(aState, content, newFrame, nsnull, blockFrame);
 
   nsresult rv = aState.AddChild(newFrame, aFrameItems, content, styleContext,
                                 aParentFrame);
@@ -4376,18 +4386,19 @@ nsCSSFrameConstructor::BeginBuildingScro
   // consistent anyway.
   CreateAnonymousFrames(aState, aContent, gfxScrollFrame, nsnull,
                         anonymousItems);
 
   aNewFrame = gfxScrollFrame;
 
   // we used the style that was passed in. So resolve another one.
   nsStyleSet *styleSet = mPresShell->StyleSet();
-  nsStyleContext* aScrolledChildStyle =
-    styleSet->ResolveAnonymousBoxStyle(aScrolledPseudo, contentStyle).get();
+  nsStyleContext* aScrolledChildStyle = styleSet->ResolvePseudoStyleFor(aContent,
+                                                                        aScrolledPseudo,
+                                                                        contentStyle).get();
 
   if (gfxScrollFrame) {
      gfxScrollFrame->SetInitialChildList(nsnull, anonymousItems);
   }
 
   return aScrolledChildStyle;
 }
 
@@ -4736,19 +4747,19 @@ nsCSSFrameConstructor::FlushAccumulatedB
     return NS_OK;
   }
 
   nsStyleContext* parentContext =
     nsFrame::CorrectStyleParentFrame(aParentFrame,
                                      nsCSSAnonBoxes::mozMathMLAnonymousBlock)->GetStyleContext(); 
   nsStyleSet *styleSet = mPresShell->StyleSet();
   nsRefPtr<nsStyleContext> blockContext;
-  blockContext = styleSet->
-    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozMathMLAnonymousBlock,
-                             parentContext);
+  blockContext = styleSet->ResolvePseudoStyleFor(aContent,
+                                                 nsCSSAnonBoxes::mozMathMLAnonymousBlock,
+                                                 parentContext);
 
   // then, create a block frame that will wrap the child frames. Make it a
   // MathML frame so that Get(Absolute/Float)ContainingBlockFor know that this
   // is not a suitable block.
   nsIFrame* blockFrame = NS_NewMathMLmathBlockFrame(mPresShell, blockContext,
                           NS_BLOCK_FLOAT_MGR | NS_BLOCK_MARGIN_ROOT);
   if (NS_UNLIKELY(!blockFrame))
     return NS_ERROR_OUT_OF_MEMORY;
@@ -5051,17 +5062,18 @@ nsCSSFrameConstructor::ConstructSVGForei
   nsresult rv = aState.AddChild(newFrame, aFrameItems, content, styleContext,
                                 aParentFrame, PR_FALSE, PR_FALSE);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   nsRefPtr<nsStyleContext> innerPseudoStyle;
   innerPseudoStyle = mPresShell->StyleSet()->
-    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozSVGForeignContent, styleContext);
+    ResolvePseudoStyleFor(content,
+                          nsCSSAnonBoxes::mozSVGForeignContent, styleContext);
 
   nsIFrame* blockFrame = NS_NewBlockFrame(mPresShell, innerPseudoStyle,
                                           NS_BLOCK_FLOAT_MGR |
                                           NS_BLOCK_MARGIN_ROOT);
   if (NS_UNLIKELY(!blockFrame)) {
     newFrame->Destroy();
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -5094,18 +5106,18 @@ nsCSSFrameConstructor::AddPageBreakItem(
 {
   nsRefPtr<nsStyleContext> pseudoStyle;
   // Use the same parent style context that |aMainStyleContext| has, since
   // that's easier to re-resolve and it doesn't matter in practice.
   // (Getting different parents can result in framechange hints, e.g.,
   // for user-modify.)
   pseudoStyle =
     mPresShell->StyleSet()->
-      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::pageBreak,
-                               aMainStyleContext->GetParent());
+      ResolvePseudoStyleFor(nsnull, nsCSSAnonBoxes::pageBreak,
+                            aMainStyleContext->GetParent());
 
   NS_ASSERTION(pseudoStyle->GetStyleDisplay()->mDisplay ==
                  NS_STYLE_DISPLAY_BLOCK, "Unexpected display");
 
   static const FrameConstructionData sPageBreakData =
     FCDATA_DECL(FCDATA_SKIP_FRAMEMAP, NS_NewPageBreakFrame);
 
   // Lie about the tag and namespace so we don't trigger anything
@@ -5695,17 +5707,17 @@ AdjustAppendParentForAfterContent(nsPres
                                   nsIContent* aContainer,
                                   nsIFrame* aParentFrame,
                                   nsIFrame** aAfterFrame)
 {
   // See if the parent has an :after pseudo-element.  Check for the presence
   // of style first, since nsLayoutUtils::GetAfterFrame is sorta expensive.
   nsStyleContext* parentStyle = aParentFrame->GetStyleContext();
   if (nsLayoutUtils::HasPseudoStyle(aContainer, parentStyle,
-                                    nsCSSPseudoElements::ePseudo_after,
+                                    nsCSSPseudoElements::after,
                                     aPresContext)) {
     nsIFrame* afterFrame = nsLayoutUtils::GetAfterFrame(aParentFrame);
     if (afterFrame) {
       *aAfterFrame = afterFrame;
       return afterFrame->GetParent();
     }
   }
 
@@ -9230,44 +9242,42 @@ nsCSSFrameConstructor::RecreateFramesFor
 // Block frame construction code
 
 already_AddRefed<nsStyleContext>
 nsCSSFrameConstructor::GetFirstLetterStyle(nsIContent* aContent,
                                            nsStyleContext* aStyleContext)
 {
   if (aContent) {
     return mPresShell->StyleSet()->
-      ResolvePseudoElementStyle(aContent,
-                                nsCSSPseudoElements::ePseudo_firstLetter,
-                                aStyleContext);
+      ResolvePseudoStyleFor(aContent,
+                            nsCSSPseudoElements::firstLetter, aStyleContext);
   }
   return nsnull;
 }
 
 already_AddRefed<nsStyleContext>
 nsCSSFrameConstructor::GetFirstLineStyle(nsIContent* aContent,
                                          nsStyleContext* aStyleContext)
 {
   if (aContent) {
     return mPresShell->StyleSet()->
-      ResolvePseudoElementStyle(aContent,
-                                nsCSSPseudoElements::ePseudo_firstLine,
-                                aStyleContext);
+      ResolvePseudoStyleFor(aContent,
+                            nsCSSPseudoElements::firstLine, aStyleContext);
   }
   return nsnull;
 }
 
 // Predicate to see if a given content (block element) has
 // first-letter style applied to it.
 PRBool
 nsCSSFrameConstructor::ShouldHaveFirstLetterStyle(nsIContent* aContent,
                                                   nsStyleContext* aStyleContext)
 {
   return nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
-                                       nsCSSPseudoElements::ePseudo_firstLetter,
+                                       nsCSSPseudoElements::firstLetter,
                                        mPresShell->GetPresContext());
 }
 
 PRBool
 nsCSSFrameConstructor::HasFirstLetterStyle(nsIFrame* aBlockFrame)
 {
   NS_PRECONDITION(aBlockFrame, "Need a frame");
   NS_ASSERTION(nsLayoutUtils::GetAsBlock(aBlockFrame),
@@ -9277,17 +9287,17 @@ nsCSSFrameConstructor::HasFirstLetterSty
 }
 
 PRBool
 nsCSSFrameConstructor::ShouldHaveFirstLineStyle(nsIContent* aContent,
                                                 nsStyleContext* aStyleContext)
 {
   PRBool hasFirstLine =
     nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
-                                  nsCSSPseudoElements::ePseudo_firstLine,
+                                  nsCSSPseudoElements::firstLine,
                                   mPresShell->GetPresContext());
   if (hasFirstLine) {
     // But disable for fieldsets
     PRInt32 namespaceID;
     nsIAtom* tag = mDocument->BindingManager()->ResolveTag(aContent,
                                                            &namespaceID);
     // This check must match the one in FindHTMLData.
     hasFirstLine = tag != nsGkAtoms::fieldset ||
@@ -9503,17 +9513,19 @@ nsCSSFrameConstructor::CreateNeededTable
     nsIContent* parentContent = aParentFrame->GetContent();
 
     if (pseudoType == nsCSSAnonBoxes::table &&
         parentStyle->GetStyleDisplay()->mDisplay == NS_STYLE_DISPLAY_INLINE) {
       pseudoType = nsCSSAnonBoxes::inlineTable;
     }
 
     nsRefPtr<nsStyleContext> wrapperStyle =
-      mPresShell->StyleSet()->ResolveAnonymousBoxStyle(pseudoType, parentStyle);
+      mPresShell->StyleSet()->ResolvePseudoStyleFor(parentContent,
+                                                    pseudoType,
+                                                    parentStyle);
     FrameConstructionItem* newItem =
       new FrameConstructionItem(&pseudoData.mFCData,
                                 // Use the content of our parent frame
                                 parentContent,
                                 // Lie about the tag; it doesn't matter anyway
                                 pseudoType,
                                 // The namespace does matter, however; it needs
                                 // to match that of our first child item to
@@ -9656,34 +9668,34 @@ nsCSSFrameConstructor::ProcessChildren(n
     // special block styles because in some cases involving table pseudo-frames
     // it has nothing to do with the parent frame's desired behavior.
     nsStyleContext* styleContext;
 
     if (aCanHaveGeneratedContent) {
       styleContext =
         nsFrame::CorrectStyleParentFrame(aFrame, nsnull)->GetStyleContext();
       // Probe for generated content before
-      CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
-                                 nsCSSPseudoElements::ePseudo_before,
+      CreateGeneratedContentItem(aState, aFrame, aContent,
+                                 styleContext, nsCSSPseudoElements::before,
                                  itemsToConstruct);
     }
 
     ChildIterator iter, last;
     for (ChildIterator::Init(aContent, &iter, &last);
          iter != last;
          ++iter) {
       PRInt32 i = iter.XBLInvolved() ? -1 : iter.position();
       AddFrameConstructionItems(aState, *iter, i, aFrame, itemsToConstruct);
     }
     itemsToConstruct.SetParentHasNoXBLChildren(!iter.XBLInvolved());
 
     if (aCanHaveGeneratedContent) {
       // Probe for generated content after
-      CreateGeneratedContentItem(aState, aFrame, aContent, styleContext,
-                                 nsCSSPseudoElements::ePseudo_after,
+      CreateGeneratedContentItem(aState, aFrame, aContent,
+                                 styleContext, nsCSSPseudoElements::after,
                                  itemsToConstruct);
     }
   }
 
   rv = ConstructFramesFromItemList(aState, itemsToConstruct, aFrame,
                                    aFrameItems);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -9726,18 +9738,19 @@ nsCSSFrameConstructor::ProcessChildren(n
                                     message,
                                     params, NS_ARRAY_LENGTH(params),
                                     mDocument->GetDocumentURI(),
                                     EmptyString(), 0, 0, // not useful
                                     nsIScriptError::warningFlag,
                                     "FrameConstructor");
 
     nsRefPtr<nsStyleContext> blockSC = mPresShell->StyleSet()->
-      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozXULAnonymousBlock,
-                               frameStyleContext);
+      ResolvePseudoStyleFor(aContent,
+                            nsCSSAnonBoxes::mozXULAnonymousBlock,
+                            frameStyleContext);
     nsIFrame *blockFrame = NS_NewBlockFrame(mPresShell, blockSC);
     // We might, in theory, want to set NS_BLOCK_FLOAT_MGR and
     // NS_BLOCK_MARGIN_ROOT, but I think it's a bad idea given that
     // a real block placed here wouldn't get those set on it.
 
     InitAndRestoreFrame(aState, aContent, aFrame, nsnull,
                         blockFrame, PR_FALSE);
 
@@ -10677,17 +10690,18 @@ nsCSSFrameConstructor::ConstructBlock(ns
     if (!columnSetFrame) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     InitAndRestoreFrame(aState, aContent, aParentFrame, nsnull, columnSetFrame);
     // See if we need to create a view
     nsHTMLContainerFrame::CreateViewForFrame(columnSetFrame, PR_FALSE);
     blockStyle = mPresShell->StyleSet()->
-      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::columnContent, aStyleContext);
+      ResolvePseudoStyleFor(aContent, nsCSSAnonBoxes::columnContent,
+                            aStyleContext);
     parent = columnSetFrame;
     *aNewFrame = columnSetFrame;
 
     SetInitialSingleChild(columnSetFrame, blockFrame);
   }
 
   blockFrame->SetStyleContextWithoutNotification(blockStyle);
   InitAndRestoreFrame(aState, aContent, parent, nsnull, blockFrame);
@@ -10881,20 +10895,21 @@ nsCSSFrameConstructor::CreateIBSiblings(
 {
   nsIContent* content = aInitialInline->GetContent();
   nsStyleContext* styleContext = aInitialInline->GetStyleContext();
   nsIFrame* parentFrame = aInitialInline->GetParent();
 
   // Resolve the right style context for our anonymous blocks.
   nsRefPtr<nsStyleContext> blockSC =
     mPresShell->StyleSet()->
-      ResolveAnonymousBoxStyle(aIsPositioned ?
-                                 nsCSSAnonBoxes::mozAnonymousPositionedBlock :
-                                 nsCSSAnonBoxes::mozAnonymousBlock,
-                               styleContext);
+      ResolvePseudoStyleFor(content,
+                            aIsPositioned ?
+                              nsCSSAnonBoxes::mozAnonymousPositionedBlock :
+                              nsCSSAnonBoxes::mozAnonymousBlock,
+                            styleContext);
 
   nsIFrame* lastNewInline = aInitialInline->GetFirstContinuation();
   do {
     // On entry to this loop aChildItems is not empty and the first frame in it
     // is block-level.
     NS_PRECONDITION(aChildItems.NotEmpty(), "Should have child items");
     NS_PRECONDITION(!IsInlineOutside(aChildItems.FirstChild()),
                     "Must have list starting with block");
@@ -10962,18 +10977,18 @@ nsCSSFrameConstructor::BuildInlineChildI
   // XXXbz should we preallocate aParentItem.mChildItems to some sane
   // length?  Maybe even to parentContent->GetChildCount()?
   nsFrameConstructorState::PendingBindingAutoPusher
     pusher(aState, aParentItem.mPendingBinding);
 
   // Probe for generated content before
   nsStyleContext* const parentStyleContext = aParentItem.mStyleContext;
   nsIContent* const parentContent = aParentItem.mContent;
-  CreateGeneratedContentItem(aState, nsnull, parentContent, parentStyleContext,
-                             nsCSSPseudoElements::ePseudo_before,
+  CreateGeneratedContentItem(aState, nsnull, parentContent,
+                             parentStyleContext, nsCSSPseudoElements::before,
                              aParentItem.mChildItems);
 
   ChildIterator iter, last;
   for (ChildIterator::Init(parentContent, &iter, &last);
        iter != last;
        ++iter) {
     // Manually check for comments/PIs, since we do't have a frame to pass to
     // AddFrameConstructionItems.  We know our parent is a non-replaced inline,
@@ -10990,18 +11005,18 @@ nsCSSFrameConstructor::BuildInlineChildI
     PRInt32 i = iter.XBLInvolved() ? -1 : iter.position();
     AddFrameConstructionItemsInternal(aState, content, nsnull, content->Tag(),
                                       content->GetNameSpaceID(), i, childContext,
                                       ITEM_ALLOW_XBL_BASE | ITEM_ALLOW_PAGE_BREAK,
                                       aParentItem.mChildItems);
   }
 
   // Probe for generated content after
-  CreateGeneratedContentItem(aState, nsnull, parentContent, parentStyleContext,
-                             nsCSSPseudoElements::ePseudo_after,
+  CreateGeneratedContentItem(aState, nsnull, parentContent,
+                             parentStyleContext, nsCSSPseudoElements::after,
                              aParentItem.mChildItems);
 
   aParentItem.mIsAllInline = aParentItem.mChildItems.AreAllItemsInline();
 }
 
 PRBool
 nsCSSFrameConstructor::WipeContainingBlock(nsFrameConstructorState& aState,
                                            nsIFrame* aContainingBlock,
--- a/layout/base/nsCSSFrameConstructor.h
+++ b/layout/base/nsCSSFrameConstructor.h
@@ -47,17 +47,16 @@
 #include "nsILayoutHistoryState.h"
 #include "nsIXBLService.h"
 #include "nsQuoteList.h"
 #include "nsCounterManager.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsThreadUtils.h"
 #include "nsPageContentFrame.h"
-#include "nsCSSPseudoElements.h"
 
 class nsIDocument;
 struct nsFrameItems;
 struct nsAbsoluteItems;
 class nsStyleContext;
 struct nsStyleContent;
 struct nsStyleDisplay;
 class nsIPresShell;
@@ -432,21 +431,21 @@ private:
    * @param aContentIndex is the index of the content item to create
    */
   already_AddRefed<nsIContent> CreateGeneratedContent(nsFrameConstructorState& aState,
                                                       nsIContent*     aParentContent,
                                                       nsStyleContext* aStyleContext,
                                                       PRUint32        aContentIndex);
 
   // aFrame may be null; this method doesn't use it directly in any case.
-  void CreateGeneratedContentItem(nsFrameConstructorState&   aState,
-                                  nsIFrame*                  aFrame,
-                                  nsIContent*                aContent,
-                                  nsStyleContext*            aStyleContext,
-                                  nsCSSPseudoElements::Type  aPseudoElement,
+  void CreateGeneratedContentItem(nsFrameConstructorState& aState,
+                                  nsIFrame*                aFrame,
+                                  nsIContent*              aContent,
+                                  nsStyleContext*          aStyleContext,
+                                  nsIAtom*                 aPseudoElement,
                                   FrameConstructionItemList& aItems);
 
   // This method can change aFrameList: it can chop off the beginning and put
   // it in aParentFrame while putting the remainder into a special sibling of
   // aParentFrame.  aPrevSibling must be the frame after which aFrameList is to
   // be placed on aParentFrame's principal child list.  It may be null if
   // aFrameList is being added at the beginning of the child list.
   nsresult AppendFrames(nsFrameConstructorState&       aState,
--- a/layout/base/nsFrameManager.cpp
+++ b/layout/base/nsFrameManager.cpp
@@ -944,17 +944,16 @@ TryStartingTransition(nsPresContext *aPr
     aPresContext->TransitionManager()->StyleContextChanged(
       aContent, aOldStyleContext, *aNewStyleContext);
   if (coverRule) {
     nsCOMArray<nsIStyleRule> rules;
     rules.AppendObject(coverRule);
     *aNewStyleContext = aPresContext->StyleSet()->ResolveStyleForRules(
                      (*aNewStyleContext)->GetParent(),
                      (*aNewStyleContext)->GetPseudo(),
-                     (*aNewStyleContext)->GetPseudoType(),
                      (*aNewStyleContext)->GetRuleNode(),
                      rules);
   }
 }
 
 nsresult
 nsFrameManager::ReParentStyleContext(nsIFrame* aFrame)
 {
@@ -1229,17 +1228,16 @@ nsFrameManager::ReResolveStyleContext(ns
   PRBool isVisible = aFrame->GetStyleVisibility()->IsVisible();
 #endif
 
   // XXXbz the nsIFrame constructor takes an nsStyleContext, so how
   // could oldContext be null?
   if (oldContext) {
     oldContext->AddRef();
     nsIAtom* const pseudoTag = oldContext->GetPseudo();
-    const nsCSSPseudoElements::Type pseudoType = oldContext->GetPseudoType();
     nsIContent* localContent = aFrame->GetContent();
     // |content| is the node that we used for rule matching of
     // normal elements (not pseudo-elements) and for which we generate
     // framechange hints if we need them.
     // XXXldb Why does it make sense to use aParentContent?  (See
     // comment above assertion at start of function.)
     nsIContent* content = localContent ? localContent : aParentContent;
 
@@ -1331,45 +1329,39 @@ nsFrameManager::ReResolveStyleContext(ns
       // boxes and perhaps other cases.
       // See also the comment above the assertion at the start of this
       // function.
       nsIContent* pseudoContent =
           aParentContent ? aParentContent : localContent;
       if (pseudoTag == nsCSSPseudoElements::before ||
           pseudoTag == nsCSSPseudoElements::after) {
         // XXX what other pseudos do we need to treat like this?
-        newContext = styleSet->ProbePseudoElementStyle(pseudoContent,
-                                                       pseudoType,
-                                                       parentContext);
+        newContext = styleSet->ProbePseudoStyleFor(pseudoContent,
+                                                   pseudoTag,
+                                                   parentContext);
         if (!newContext) {
           // This pseudo should no longer exist; gotta reframe
           NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame);
           aChangeList->AppendChange(aFrame, pseudoContent,
                                     nsChangeHint_ReconstructFrame);
           // We're reframing anyway; just keep the same context
           newContext = oldContext;
         }
-      } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
-        newContext = styleSet->ResolveAnonymousBoxStyle(pseudoTag,
-                                                        parentContext);
       } else {
-        // Don't expect XUL tree stuff here, since it needs a comparator and
-        // all.
-        NS_ASSERTION(pseudoType <
-                       nsCSSPseudoElements::ePseudo_PseudoElementCount,
-                     "Unexpected pseudo type");
         if (pseudoTag == nsCSSPseudoElements::firstLetter) {
           NS_ASSERTION(aFrame->GetType() == nsGkAtoms::letterFrame, 
                        "firstLetter pseudoTag without a nsFirstLetterFrame");
           nsBlockFrame* block = nsBlockFrame::GetNearestAncestorBlock(aFrame);
           pseudoContent = block->GetContent();
+        } else if (pseudoTag == nsCSSAnonBoxes::pageBreak) {
+          pseudoContent = nsnull;
         }
-        newContext = styleSet->ResolvePseudoElementStyle(pseudoContent,
-                                                         pseudoType,
-                                                         parentContext);
+        newContext = styleSet->ResolvePseudoStyleFor(pseudoContent,
+                                                     pseudoTag,
+                                                     parentContext);
       }
     }
     else {
       NS_ASSERTION(localContent,
                    "non pseudo-element frame without content node");
       newContext = styleSet->ResolveStyleFor(content, parentContext);
     }
     NS_ASSERTION(newContext, "failed to get new style context");
@@ -1409,35 +1401,22 @@ nsFrameManager::ReResolveStyleContext(ns
     // do additional contexts 
     PRInt32 contextIndex = -1;
     while (1 == 1) {
       nsStyleContext* oldExtraContext = nsnull;
       oldExtraContext = aFrame->GetAdditionalStyleContext(++contextIndex);
       if (oldExtraContext) {
         nsRefPtr<nsStyleContext> newExtraContext;
         nsIAtom* const extraPseudoTag = oldExtraContext->GetPseudo();
-        const nsCSSPseudoElements::Type extraPseudoType =
-          oldExtraContext->GetPseudoType();
         NS_ASSERTION(extraPseudoTag &&
                      extraPseudoTag != nsCSSAnonBoxes::mozNonElement,
                      "extra style context is not pseudo element");
-        if (extraPseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
-          newExtraContext = styleSet->ResolveAnonymousBoxStyle(extraPseudoTag,
-                                                               newContext);
-        }
-        else {
-          // Don't expect XUL tree stuff here, since it needs a comparator and
-          // all.
-          NS_ASSERTION(extraPseudoType <
-                         nsCSSPseudoElements::ePseudo_PseudoElementCount,
-                       "Unexpected type");
-          newExtraContext = styleSet->ResolvePseudoElementStyle(content,
-                                                                extraPseudoType,
-                                                                newContext);
-        }
+        newExtraContext = styleSet->ResolvePseudoStyleFor(content,
+                                                          extraPseudoTag,
+                                                          newContext);
         if (newExtraContext) {
           if (oldExtraContext != newExtraContext) {
             aMinChange = CaptureChange(oldExtraContext, newExtraContext,
                                        aFrame, content, aChangeList,
                                        aMinChange, assumeDifferenceHint);
             if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
               aFrame->SetAdditionalStyleContext(contextIndex, newExtraContext);
             }
@@ -1505,17 +1484,17 @@ nsFrameManager::ReResolveStyleContext(ns
         // Check for a new :before pseudo and an existing :before
         // frame, but only if the frame is the first continuation.
         nsIFrame* prevContinuation = aFrame->GetPrevContinuation();
         if (!prevContinuation) {
           // Checking for a :before frame is cheaper than getting the
           // :before style context.
           if (!nsLayoutUtils::GetBeforeFrame(aFrame) &&
               nsLayoutUtils::HasPseudoStyle(localContent, newContext,
-                                            nsCSSPseudoElements::ePseudo_before,
+                                            nsCSSPseudoElements::before,
                                             aPresContext)) {
             // Have to create the new :before frame
             NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame);
             aChangeList->AppendChange(aFrame, content,
                                       nsChangeHint_ReconstructFrame);
           }
         }
       }
@@ -1531,17 +1510,17 @@ nsFrameManager::ReResolveStyleContext(ns
         // Check for new :after content, but only if the frame is the
         // last continuation.
         nsIFrame* nextContinuation = aFrame->GetNextContinuation();
 
         if (!nextContinuation) {
           // Getting the :after frame is more expensive than getting the pseudo
           // context, so get the pseudo context first.
           if (nsLayoutUtils::HasPseudoStyle(localContent, newContext,
-                                            nsCSSPseudoElements::ePseudo_after,
+                                            nsCSSPseudoElements::after,
                                             aPresContext) &&
               !nsLayoutUtils::GetAfterFrame(aFrame)) {
             // have to create the new :after frame
             NS_UpdateHint(aMinChange, nsChangeHint_ReconstructFrame);
             aChangeList->AppendChange(aFrame, content,
                                       nsChangeHint_ReconstructFrame);
           }
         }      
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -59,17 +59,16 @@ class nsClientRectList;
 #include "nsStyleSet.h"
 #include "nsIView.h"
 #include "nsIFrame.h"
 #include "nsThreadUtils.h"
 #include "nsIPresShell.h"
 #include "nsIPrincipal.h"
 #include "gfxPattern.h"
 #include "imgIContainer.h"
-#include "nsCSSPseudoElements.h"
 
 class nsBlockFrame;
 class nsTextFragment;
 
 /**
  * nsLayoutUtils is a namespace class used for various helper
  * functions that are useful in multiple places in layout.  The goal
  * is not to define multiple copies of the same static helper.
@@ -323,31 +322,32 @@ public:
 
   /**
    * HasPseudoStyle returns PR_TRUE if aContent (whose primary style
    * context is aStyleContext) has the aPseudoElement pseudo-style
    * attached to it; returns PR_FALSE otherwise.
    *
    * @param aContent the content node we're looking at
    * @param aStyleContext aContent's style context
-   * @param aPseudoElement the id of the pseudo style we care about
+   * @param aPseudoElement the name of the pseudo style we care about
    * @param aPresContext the presentation context
    * @return whether aContent has aPseudoElement style attached to it
    */
   static PRBool HasPseudoStyle(nsIContent* aContent,
                                nsStyleContext* aStyleContext,
-                               nsCSSPseudoElements::Type aPseudoElement,
+                               nsIAtom* aPseudoElement,
                                nsPresContext* aPresContext)
   {
     NS_PRECONDITION(aPresContext, "Must have a prescontext");
+    NS_PRECONDITION(aPseudoElement, "Must have a pseudo name");
 
     nsRefPtr<nsStyleContext> pseudoContext;
     if (aContent) {
       pseudoContext = aPresContext->StyleSet()->
-        ProbePseudoElementStyle(aContent, aPseudoElement, aStyleContext);
+        ProbePseudoStyleFor(aContent, aPseudoElement, aStyleContext);
     }
     return pseudoContext != nsnull;
   }
 
   /**
    * If this frame is a placeholder for a float, then return the float,
    * otherwise return nsnull.  aPlaceholder must be a placeholder frame.
    */
--- a/layout/forms/nsButtonFrameRenderer.cpp
+++ b/layout/forms/nsButtonFrameRenderer.cpp
@@ -380,26 +380,24 @@ nsButtonFrameRenderer::GetAddedButtonBor
 void
 nsButtonFrameRenderer::ReResolveStyles(nsPresContext* aPresContext)
 {
   // get all the styles
   nsStyleContext* context = mFrame->GetStyleContext();
   nsStyleSet *styleSet = aPresContext->StyleSet();
 
   // style for the inner such as a dotted line (Windows)
-  mInnerFocusStyle =
-    styleSet->ProbePseudoElementStyle(mFrame->GetContent(),
-                                      nsCSSPseudoElements::ePseudo_mozFocusInner,
-                                      context);
+  mInnerFocusStyle = styleSet->ProbePseudoStyleFor(mFrame->GetContent(),
+                                                   nsCSSPseudoElements::mozFocusInner,
+                                                   context);
 
   // style for outer focus like a ridged border (MAC).
-  mOuterFocusStyle =
-    styleSet->ProbePseudoElementStyle(mFrame->GetContent(),
-                                      nsCSSPseudoElements::ePseudo_mozFocusOuter,
-                                      context);
+  mOuterFocusStyle = styleSet->ProbePseudoStyleFor(mFrame->GetContent(),
+                                                   nsCSSPseudoElements::mozFocusOuter,
+                                                   context);
 }
 
 nsStyleContext*
 nsButtonFrameRenderer::GetStyleContext(PRInt32 aIndex) const
 {
   switch (aIndex) {
   case NS_BUTTON_RENDERER_FOCUS_INNER_CONTEXT_INDEX:
     return mInnerFocusStyle;
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -1157,18 +1157,19 @@ nsComboboxControlFrame::CreateFrameFor(n
   
   // Get PresShell
   nsIPresShell *shell = PresContext()->PresShell();
   nsStyleSet *styleSet = shell->StyleSet();
 
   // create the style contexts for the anonymous block frame and text frame
   nsRefPtr<nsStyleContext> styleContext;
   styleContext = styleSet->
-    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozDisplayComboboxControlFrame,
-                             mStyleContext);
+    ResolvePseudoStyleFor(mContent, 
+                          nsCSSAnonBoxes::mozDisplayComboboxControlFrame,
+                          mStyleContext);
   if (NS_UNLIKELY(!styleContext)) {
     return nsnull;
   }
 
   nsRefPtr<nsStyleContext> textStyleContext;
   textStyleContext = styleSet->ResolveStyleForNonElement(mStyleContext);
   if (NS_UNLIKELY(!textStyleContext)) {
     return nsnull;
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -6360,35 +6360,34 @@ nsBlockFrame::SetInitialChildList(nsIAto
     // here so that RenumberLists will work (it needs the bullets to
     // store the bullet numbers).
     const nsStyleDisplay* styleDisplay = GetStyleDisplay();
     if ((nsnull == GetPrevInFlow()) &&
         (NS_STYLE_DISPLAY_LIST_ITEM == styleDisplay->mDisplay) &&
         (nsnull == mBullet)) {
       // Resolve style for the bullet frame
       const nsStyleList* styleList = GetStyleList();
-      nsCSSPseudoElements::Type pseudoType;
+      nsIAtom *pseudoElement;
       switch (styleList->mListStyleType) {
         case NS_STYLE_LIST_STYLE_DISC:
         case NS_STYLE_LIST_STYLE_CIRCLE:
         case NS_STYLE_LIST_STYLE_SQUARE:
-          pseudoType = nsCSSPseudoElements::ePseudo_mozListBullet;
+          pseudoElement = nsCSSPseudoElements::mozListBullet;
           break;
         default:
-          pseudoType = nsCSSPseudoElements::ePseudo_mozListNumber;
+          pseudoElement = nsCSSPseudoElements::mozListNumber;
           break;
       }
 
       nsIPresShell *shell = presContext->PresShell();
 
       nsStyleContext* parentStyle =
-        CorrectStyleParentFrame(this,
-          nsCSSPseudoElements::GetPseudoAtom(pseudoType))->GetStyleContext();
+        CorrectStyleParentFrame(this, pseudoElement)->GetStyleContext();
       nsRefPtr<nsStyleContext> kidSC = shell->StyleSet()->
-        ResolvePseudoElementStyle(mContent, pseudoType, parentStyle);
+        ResolvePseudoStyleFor(mContent, pseudoElement, parentStyle);
 
       // Create bullet frame
       nsBulletFrame* bullet = new (shell) nsBulletFrame(kidSC);
       if (nsnull == bullet) {
         return NS_ERROR_OUT_OF_MEMORY;
       }
       bullet->Init(mContent, this, nsnull);
 
--- a/layout/generic/nsBlockFrame.h
+++ b/layout/generic/nsBlockFrame.h
@@ -332,19 +332,18 @@ protected:
 #endif
   }
   virtual ~nsBlockFrame();
 
 #ifdef DEBUG
   already_AddRefed<nsStyleContext> GetFirstLetterStyle(nsPresContext* aPresContext)
   {
     return aPresContext->StyleSet()->
-      ProbePseudoElementStyle(mContent,
-                              nsCSSPseudoElements::ePseudo_firstLetter,
-                              mStyleContext);
+      ProbePseudoStyleFor(mContent,
+                          nsCSSPseudoElements::firstLetter, mStyleContext);
   }
 #endif
 
   /*
    * Overides member function of nsHTMLContainerFrame. Needed to handle the 
    * lines in a nsBlockFrame properly.
    */
   virtual void PaintTextDecorationLine(gfxContext* aCtx,
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -63,16 +63,17 @@
 #include "nsILookAndFeel.h"
 #include "nsWidgetsCID.h"
 #include "nsIComponentManager.h"
 #include "nsGUIEvent.h"
 #include "nsIRenderingContext.h"
 #include "nsIServiceManager.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsINameSpaceManager.h"
+#include "nsCSSPseudoElements.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsAutoPtr.h"
 #include "nsStyleSet.h"
 #include "nsIContent.h"
 #include "nsDisplayList.h"
 #include "nsNodeUtils.h"
 #include "mozAutoDocUpdate.h"
 
@@ -424,17 +425,17 @@ nsHTMLFramesetFrame::Init(nsIContent*   
     }
   }
 
   mNonBlankChildCount = mChildCount;
   // add blank frames for frameset cells that had no content provided
   for (int blankX = mChildCount; blankX < numCells; blankX++) {
     nsRefPtr<nsStyleContext> pseudoStyleContext;
     pseudoStyleContext = shell->StyleSet()->
-      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::framesetBlank, mStyleContext);
+      ResolvePseudoStyleFor(nsnull, nsCSSAnonBoxes::framesetBlank, mStyleContext);
     if (!pseudoStyleContext) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     // XXX the blank frame is using the content of its parent - at some point it 
     // should just have null content, if we support that                                                            
     nsHTMLFramesetBlankFrame* blankFrame = new (shell) nsHTMLFramesetBlankFrame(pseudoStyleContext);
     if (!blankFrame)
@@ -1036,19 +1037,19 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
     GetSizeOfChildAt(childX, size, cellIndex);
 
     if (lastRow != cellIndex.y) {  // changed to next row
       offset.x = 0;
       offset.y += lastSize.height;
       if (firstTime) { // create horizontal border
 
         nsRefPtr<nsStyleContext> pseudoStyleContext;
-        pseudoStyleContext = styleSet->
-          ResolveAnonymousBoxStyle(nsCSSAnonBoxes::horizontalFramesetBorder,
-                                   mStyleContext);
+        pseudoStyleContext = styleSet->ResolvePseudoStyleFor(mContent,
+                                                             nsCSSPseudoElements::horizontalFramesetBorder,
+                                                             mStyleContext);
 
         borderFrame = new (shell) nsHTMLFramesetBorderFrame(pseudoStyleContext,
                                                             borderWidth,
                                                             PR_FALSE,
                                                             PR_FALSE);
         if (NS_LIKELY(borderFrame != nsnull)) {
           borderFrame->Init(mContent, this, nsnull);
           mChildCount++;
@@ -1072,19 +1073,19 @@ nsHTMLFramesetFrame::Reflow(nsPresContex
       }
       offset.y += borderWidth;
     } else {
       if (cellIndex.x > 0) {  // moved to next col in same row
         if (0 == cellIndex.y) { // in 1st row
           if (firstTime) { // create vertical border
             
             nsRefPtr<nsStyleContext> pseudoStyleContext;
-            pseudoStyleContext = styleSet->
-              ResolveAnonymousBoxStyle(nsCSSAnonBoxes::verticalFramesetBorder,
-                                       mStyleContext);
+            pseudoStyleContext = styleSet->ResolvePseudoStyleFor(mContent,
+                                                                 nsCSSPseudoElements::verticalFramesetBorder,
+                                                                 mStyleContext);
 
             borderFrame = new (shell) nsHTMLFramesetBorderFrame(pseudoStyleContext, 
                                                                 borderWidth,
                                                                 PR_TRUE,
                                                                 PR_FALSE);
             if (NS_LIKELY(borderFrame != nsnull)) {
               borderFrame->Init(mContent, this, nsnull);
               mChildCount++;
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -1052,17 +1052,18 @@ nsFirstLineFrame::Reflow(nsPresContext* 
       nsStyleContext* parentContext = first->GetParent()->GetStyleContext();
       if (parentContext) {
         // Create a new style context that is a child of the parent
         // style context thus removing the :first-line style. This way
         // we behave as if an anonymous (unstyled) span was the child
         // of the parent frame.
         nsRefPtr<nsStyleContext> newSC;
         newSC = aPresContext->StyleSet()->
-          ResolveAnonymousBoxStyle(nsCSSAnonBoxes::mozLineFrame, parentContext);
+          ResolvePseudoStyleFor(nsnull,
+                                nsCSSAnonBoxes::mozLineFrame, parentContext);
         if (newSC) {
           // Switch to the new style context.
           SetStyleContext(newSC);
 
           // Re-resolve all children
           ReParentChildListStyle(aPresContext, mFrames, this);
         }
       }
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -3157,19 +3157,18 @@ nsTextPaintStyle::InitSelectionColors()
 
   nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(mFrame);
   nsIContent* selectionContent = FindElementAncestor(nonGeneratedAncestor->GetContent());
 
   if (selectionContent &&
       selectionStatus == nsISelectionController::SELECTION_ON) {
     nsRefPtr<nsStyleContext> sc = nsnull;
     sc = mPresContext->StyleSet()->
-      ProbePseudoElementStyle(selectionContent,
-                              nsCSSPseudoElements::ePseudo_mozSelection,
-                              mFrame->GetStyleContext());
+      ProbePseudoStyleFor(selectionContent, nsCSSPseudoElements::mozSelection,
+                          mFrame->GetStyleContext());
     // Use -moz-selection pseudo class.
     if (sc) {
       const nsStyleBackground* bg = sc->GetStyleBackground();
       mSelectionBGColor = bg->mBackgroundColor;
       mSelectionTextColor = sc->GetStyleColor()->mColor;
       return PR_TRUE;
     }
   }
--- a/layout/mathml/mathml.css
+++ b/layout/mathml/mathml.css
@@ -60,16 +60,19 @@ math {
 }
 math[mode="display"], math[display="block"] {
   display: block;
   text-align: -moz-center;
 }
 math[display="inline"] {
   display: inline;
 }
+::-moz-math-inline {
+  display: inline;
+}
 
 /**************************************************************************/
 /* Style switching during frame construction depending on the context of <mi>:
    These rules are not used when mathvariant or fontstyle is specified
    explicitly. 
 /**************************************************************************/
 
 /* If the textual content of an <mi> consists of a single character
@@ -400,21 +403,18 @@ mtd[-moz-math-columnline="dashed"] {
    clicking the pref to override document fonts.
 /**************************************************************************/
 
 ::-moz-math-stretchy {
   font-style: normal;
   font-family: serif; /* an empty family is ignored as an error and behaves like inherit */
 /*  background-color: #3C6; */
 }
-/* Don't actually style -moz-math-anonymous by default */
-/*
 ::-moz-math-anonymous {
 }
-*/
 
 /**********************************************************************/
 /* Hide embedded semantic MathML content (as opposed to presentational
    content, which we render). Ideally, here is the behavior that we want:
 
    if there is an annotation-xml[encoding="MathML-Presentation"]
      render that annotation, and ignore the first child of the
      <semantics> element and all other annotations, 
--- a/layout/mathml/nsMathMLFrame.cpp
+++ b/layout/mathml/nsMathMLFrame.cpp
@@ -34,17 +34,17 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsINameSpaceManager.h"
 #include "nsMathMLFrame.h"
 #include "nsMathMLChar.h"
-#include "nsCSSPseudoElements.h"
+#include "nsCSSAnonBoxes.h"
 
 // used to map attributes into CSS rules
 #include "nsIDocument.h"
 #include "nsStyleSet.h"
 #include "nsIStyleSheet.h"
 #include "nsICSSStyleSheet.h"
 #include "nsIDOMCSSStyleSheet.h"
 #include "nsICSSRule.h"
@@ -159,22 +159,22 @@ nsMathMLFrame::UpdatePresentationData(PR
 // the Style System via the Get/Set AdditionalStyleContext() APIs.
 /* static */ void
 nsMathMLFrame::ResolveMathMLCharStyle(nsPresContext*  aPresContext,
                                       nsIContent*      aContent,
                                       nsStyleContext*  aParentStyleContext,
                                       nsMathMLChar*    aMathMLChar,
                                       PRBool           aIsMutableChar)
 {
-  nsCSSPseudoElements::Type pseudoType = (aIsMutableChar) ?
-    nsCSSPseudoElements::ePseudo_mozMathStretchy :
-    nsCSSPseudoElements::ePseudo_mozMathAnonymous; // savings
+  nsIAtom* pseudoStyle = (aIsMutableChar) ?
+    nsCSSAnonBoxes::mozMathStretchy :
+    nsCSSAnonBoxes::mozMathAnonymous; // savings
   nsRefPtr<nsStyleContext> newStyleContext;
   newStyleContext = aPresContext->StyleSet()->
-    ResolvePseudoElementStyle(aContent, pseudoType, aParentStyleContext);
+    ResolvePseudoStyleFor(aContent, pseudoStyle, aParentStyleContext);
 
   if (newStyleContext)
     aMathMLChar->SetStyleContext(newStyleContext);
 }
 
 /* static */ void
 nsMathMLFrame::GetEmbellishDataFrom(nsIFrame*        aFrame,
                                     nsEmbellishData& aEmbellishData)
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -254,16 +254,20 @@ select:empty {
   white-space: nowrap;
   text-align: inherit;
   -moz-user-select: none;
   /* Make sure to size correctly if the combobox has a non-auto height. */
   height: 100% ! important;
   -moz-box-sizing: border-box ! important;
 }
 
+select::-moz-scrolled-content {
+  display: block !important;
+}
+
 option {
   display: block;
   float: none !important;
   position: static !important;
   min-height: 1em;
   line-height: normal !important;
   -moz-user-select: none;
   text-indent: 0;
--- a/layout/style/nsCSSAnonBoxList.h
+++ b/layout/style/nsCSSAnonBoxList.h
@@ -54,20 +54,16 @@
 
 CSS_ANON_BOX(mozNonElement, ":-moz-non-element")
 
 CSS_ANON_BOX(mozAnonymousBlock, ":-moz-anonymous-block")
 CSS_ANON_BOX(mozAnonymousPositionedBlock, ":-moz-anonymous-positioned-block")
 CSS_ANON_BOX(mozMathMLAnonymousBlock, ":-moz-mathml-anonymous-block")
 CSS_ANON_BOX(mozXULAnonymousBlock, ":-moz-xul-anonymous-block")
 
-// Framesets
-CSS_ANON_BOX(horizontalFramesetBorder, ":-moz-hframeset-border")
-CSS_ANON_BOX(verticalFramesetBorder, ":-moz-vframeset-border")
-
 CSS_ANON_BOX(mozLineFrame, ":-moz-line-frame")
 
 CSS_ANON_BOX(buttonContent, ":-moz-button-content")
 CSS_ANON_BOX(mozButtonLabel, ":-moz-buttonlabel")
 CSS_ANON_BOX(cellContent, ":-moz-cell-content")
 CSS_ANON_BOX(dropDownList, ":-moz-dropdown-list")
 CSS_ANON_BOX(fieldsetContent, ":-moz-fieldset-content")
 CSS_ANON_BOX(framesetBlank, ":-moz-frameset-blank")
@@ -104,11 +100,17 @@ CSS_ANON_BOX(moztreeline, ":-moz-tree-li
 CSS_ANON_BOX(moztreetwisty, ":-moz-tree-twisty")
 CSS_ANON_BOX(moztreeimage, ":-moz-tree-image")
 CSS_ANON_BOX(moztreecelltext, ":-moz-tree-cell-text")
 CSS_ANON_BOX(moztreecheckbox, ":-moz-tree-checkbox")
 CSS_ANON_BOX(moztreeprogressmeter, ":-moz-tree-progressmeter")
 CSS_ANON_BOX(moztreedropfeedback, ":-moz-tree-drop-feedback")
 #endif
 
+#ifdef MOZ_MATHML
+CSS_ANON_BOX(mozMathStretchy, ":-moz-math-stretchy")
+CSS_ANON_BOX(mozMathAnonymous, ":-moz-math-anonymous")
+CSS_ANON_BOX(mozMathInline, ":-moz-math-inline")
+#endif
+
 #ifdef MOZ_SVG
 CSS_ANON_BOX(mozSVGForeignContent, ":-moz-svg-foreign-content")
 #endif
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -349,41 +349,37 @@ protected:
   // aPseudoElement and aPseudoElementArgs are the location where
   // pseudo-elements (as opposed to pseudo-classes) are stored;
   // pseudo-classes are stored on aSelector.  aPseudoElement and
   // aPseudoElementArgs must be non-null iff !aIsNegated.
   nsSelectorParsingStatus ParsePseudoSelector(PRInt32&       aDataMask,
                                               nsCSSSelector& aSelector,
                                               PRBool         aIsNegated,
                                               nsIAtom**      aPseudoElement,
-                                              nsPseudoClassList** aPseudoElementArgs,
-                                              nsCSSPseudoElements::Type* aPseudoElementType);
+                                              nsPseudoClassList** aPseudoElementArgs);
 
   nsSelectorParsingStatus ParseAttributeSelector(PRInt32&       aDataMask,
                                                  nsCSSSelector& aSelector);
 
   nsSelectorParsingStatus ParseTypeOrUniversalSelector(PRInt32&       aDataMask,
                                                        nsCSSSelector& aSelector,
                                                        PRBool         aIsNegated);
 
   nsSelectorParsingStatus ParsePseudoClassWithIdentArg(nsCSSSelector& aSelector,
-                                                       nsIAtom*       aPseudo,
-                                                       nsCSSPseudoClasses::Type aType);
+                                                       nsIAtom*       aPseudo);
 
   nsSelectorParsingStatus ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
-                                                         nsIAtom*       aPseudo,
-                                                         nsCSSPseudoClasses::Type aType);
+                                                         nsIAtom*       aPseudo);
 
   nsSelectorParsingStatus ParseNegatedSimpleSelector(PRInt32&       aDataMask,
                                                      nsCSSSelector& aSelector);
 
   nsSelectorParsingStatus ParseSelector(nsCSSSelector& aSelectorResult,
                                         nsIAtom** aPseudoElement,
-                                        nsPseudoClassList** aPseudoElementArgs,
-                                        nsCSSPseudoElements::Type* aPseudoElementType);
+                                        nsPseudoClassList** aPseudoElementArgs);
 
   // If aTerminateAtBrace is true, the selector list is done when we
   // hit a '{'.  Otherwise, it's done when we hit EOF.
   PRBool ParseSelectorList(nsCSSSelectorList*& aListHead,
                            PRBool aTerminateAtBrace);
   PRBool ParseSelectorGroup(nsCSSSelectorList*& aListHead);
   nsCSSDeclaration* ParseDeclarationBlock(PRBool aCheckForBraces);
   PRBool ParseDeclaration(nsCSSDeclaration* aDeclaration,
@@ -2496,54 +2492,46 @@ CSSParserImpl::ParseSelectorGroup(nsCSSS
   while (!done) {
     nsAutoPtr<nsCSSSelector> newSelector(new nsCSSSelector());
     if (!newSelector) {
       mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
       return PR_FALSE;
     }
     nsCOMPtr<nsIAtom> pseudoElement;
     nsAutoPtr<nsPseudoClassList> pseudoElementArgs;
-    nsCSSPseudoElements::Type pseudoElementType;
     nsSelectorParsingStatus parsingStatus =
       ParseSelector(*newSelector, getter_AddRefs(pseudoElement),
-                    getter_Transfers(pseudoElementArgs),
-                    &pseudoElementType);
+                    getter_Transfers(pseudoElementArgs));
     if (parsingStatus == eSelectorParsingStatus_Empty) {
       if (!list) {
         REPORT_UNEXPECTED(PESelectorGroupNoSelector);
       }
       break;
     }
     if (parsingStatus == eSelectorParsingStatus_Error) {
       list = nsnull;
       break;
     }
-    if (pseudoElementType == nsCSSPseudoElements::ePseudo_AnonBox &&
-        (list || !IsUniversalSelector(*newSelector))) {
-      REPORT_UNEXPECTED(PEAnonBoxNotAlone);
-      list = nsnull;
-      break;
-    }
     if (nsnull == list) {
       list = new nsCSSSelectorList();
       if (nsnull == list) {
         mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
         return PR_FALSE;
       }
     }
-
     list->AddSelector(newSelector);
     nsCSSSelector* listSel = list->mSelectors;
 
     // We got a pseudo-element (or anonymous box).  We actually
     // represent pseudo-elements as a child of the rest of the selector.
     if (pseudoElement) {
-      if (pseudoElementType != nsCSSPseudoElements::ePseudo_AnonBox) {
+      if (listSel->mNext || !IsUniversalSelector(*listSel)) {
         // We need to put the pseudo-element on a new selector that's a
-        // child of the current one.
+        // child of the current one.  (If it's the only thing in the
+        // entire selector group, we can just put it on this one.)
         listSel->mOperator = PRUnichar('>');
         nsAutoPtr<nsCSSSelector> empty(new nsCSSSelector());
         if (!empty) {
           mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
           return PR_FALSE;
         }
         list->AddSelector(empty);
         // Save the weight of the non-pseudo-element part of this selector now
@@ -2551,17 +2539,16 @@ CSSParserImpl::ParseSelectorGroup(nsCSSS
         listSel = list->mSelectors; // use the new one for the pseudo
       }
       NS_ASSERTION(!listSel->mLowercaseTag &&
                    !listSel->mCasedTag &&
                    !listSel->mPseudoClassList,
                    "already initialized");
       listSel->mLowercaseTag.swap(pseudoElement);
       listSel->mPseudoClassList = pseudoElementArgs.forget();
-      listSel->SetPseudoType(pseudoElementType);
       havePseudoElement = PR_TRUE;
     }
 
     combinator = PRUnichar(0);
     if (!GetToken(PR_FALSE)) {
       break;
     }
 
@@ -2999,18 +2986,17 @@ CSSParserImpl::ParseAttributeSelector(PR
 //
 // Parse pseudo-classes and pseudo-elements
 //
 CSSParserImpl::nsSelectorParsingStatus
 CSSParserImpl::ParsePseudoSelector(PRInt32&       aDataMask,
                                    nsCSSSelector& aSelector,
                                    PRBool         aIsNegated,
                                    nsIAtom**      aPseudoElement,
-                                   nsPseudoClassList** aPseudoElementArgs,
-                                   nsCSSPseudoElements::Type* aPseudoElementType)
+                                   nsPseudoClassList** aPseudoElementArgs)
 {
   NS_ASSERTION(aIsNegated || (aPseudoElement && aPseudoElementArgs),
                "expected location to store pseudo element");
   NS_ASSERTION(!aIsNegated || (!aPseudoElement && !aPseudoElementArgs),
                "negated selectors shouldn't have a place to store "
                "pseudo elements");
   if (! GetToken(PR_FALSE)) { // premature eof
     REPORT_UNEXPECTED_EOF(PEPseudoSelEOF);
@@ -3044,46 +3030,33 @@ CSSParserImpl::ParsePseudoSelector(PRInt
   nsCOMPtr<nsIAtom> pseudo = do_GetAtom(buffer);
   if (!pseudo) {
     mScanner.SetLowLevelError(NS_ERROR_OUT_OF_MEMORY);
     return eSelectorParsingStatus_Error;
   }
 
   // stash away some info about this pseudo so we only have to get it once.
   PRBool isTreePseudo = PR_FALSE;
-  nsCSSPseudoElements::Type pseudoElementType =
-    nsCSSPseudoElements::GetPseudoType(pseudo);
 #ifdef MOZ_XUL
-  isTreePseudo = (pseudoElementType == nsCSSPseudoElements::ePseudo_XULTree);
+  isTreePseudo = nsCSSAnonBoxes::IsTreePseudoElement(pseudo);
   // If a tree pseudo-element is using the function syntax, it will
   // get isTree set here and will pass the check below that only
   // allows functions if they are in our list of things allowed to be
   // functions.  If it is _not_ using the function syntax, isTree will
   // be false, and it will still pass that check.  So the tree
   // pseudo-elements are allowed to be either functions or not, as
   // desired.
   PRBool isTree = (eCSSToken_Function == mToken.mType) && isTreePseudo;
 #endif
-  PRBool isPseudoElement =
-    (pseudoElementType < nsCSSPseudoElements::ePseudo_PseudoElementCount);
+  PRBool isPseudoElement = nsCSSPseudoElements::IsPseudoElement(pseudo);
   // anonymous boxes are only allowed if they're the tree boxes or we have
   // enabled unsafe rules
-  PRBool isAnonBox = isTreePseudo ||
-    (pseudoElementType == nsCSSPseudoElements::ePseudo_AnonBox &&
-     mUnsafeRulesEnabled);
-  nsCSSPseudoClasses::Type pseudoClassType =
-    nsCSSPseudoClasses::GetPseudoType(pseudo);
-  PRBool isPseudoClass =
-    (pseudoClassType != nsCSSPseudoClasses::ePseudoClass_NotPseudoClass);
-
-  NS_ASSERTION(!isPseudoClass ||
-               pseudoElementType == nsCSSPseudoElements::ePseudo_NotPseudoElement,
-               "Why is this atom both a pseudo-class and a pseudo-element?");
-  NS_ASSERTION(isPseudoClass + isPseudoElement + isAnonBox <= 1,
-               "Shouldn't be more than one of these");
+  PRBool isAnonBox = nsCSSAnonBoxes::IsAnonBox(pseudo) &&
+    (mUnsafeRulesEnabled || isTreePseudo);
+  PRBool isPseudoClass = nsCSSPseudoClasses::IsPseudoClass(pseudo);
 
   if (!isPseudoClass && !isPseudoElement && !isAnonBox) {
     // Not a pseudo-class, not a pseudo-element.... forget it
     REPORT_UNEXPECTED_TOKEN(PEPseudoSelUnknown);
     UngetToken();
     return eSelectorParsingStatus_Error;
   }
 
@@ -3124,30 +3097,30 @@ CSSParserImpl::ParsePseudoSelector(PRInt
     if (eSelectorParsingStatus_Continue != parsingStatus) {
       return parsingStatus;
     }
   }
   else if (!parsingPseudoElement && isPseudoClass) {
     aDataMask |= SEL_MASK_PCLASS;
     if (nsCSSPseudoClasses::HasStringArg(pseudo)) {
       nsSelectorParsingStatus parsingStatus =
-        ParsePseudoClassWithIdentArg(aSelector, pseudo, pseudoClassType);
+        ParsePseudoClassWithIdentArg(aSelector, pseudo);
       if (eSelectorParsingStatus_Continue != parsingStatus) {
         return parsingStatus;
       }
     }
     else if (nsCSSPseudoClasses::HasNthPairArg(pseudo)) {
       nsSelectorParsingStatus parsingStatus =
-        ParsePseudoClassWithNthPairArg(aSelector, pseudo, pseudoClassType);
+        ParsePseudoClassWithNthPairArg(aSelector, pseudo);
       if (eSelectorParsingStatus_Continue != parsingStatus) {
         return parsingStatus;
       }
     }
     else {
-      aSelector.AddPseudoClass(pseudo, pseudoClassType);
+      aSelector.AddPseudoClass(pseudo);
     }
   }
   else if (isPseudoElement || isAnonBox) {
     // Pseudo-element.  Make some more sanity checks.
 
     if (aIsNegated) { // pseudo-elements can't be negated
       REPORT_UNEXPECTED_TOKEN(PEPseudoSelPEInNot);
       UngetToken();
@@ -3166,17 +3139,16 @@ CSSParserImpl::ParsePseudoSelector(PRInt
       REPORT_UNEXPECTED_TOKEN(PEPseudoSelNewStyleOnly);
       UngetToken();
       return eSelectorParsingStatus_Error;
     }
 
     if (0 == (aDataMask & SEL_MASK_PELEM)) {
       aDataMask |= SEL_MASK_PELEM;
       NS_ADDREF(*aPseudoElement = pseudo);
-      *aPseudoElementType = pseudoElementType;
 
 #ifdef MOZ_XUL
       if (isTree) {
         // We have encountered a pseudoelement of the form
         // -moz-tree-xxxx(a,b,c).  We parse (a,b,c) and add each
         // item in the list to the pseudoclass list.  They will be pulled
         // from the list later along with the pseudo-element.
         if (!ParseTreePseudoElement(aPseudoElementArgs)) {
@@ -3258,17 +3230,17 @@ CSSParserImpl::ParseNegatedSimpleSelecto
   if (eCSSToken_ID == mToken.mType) { // #id
     parsingStatus = ParseIDSelector(aDataMask, *newSel);
   }
   else if (mToken.IsSymbol('.')) {    // .class
     parsingStatus = ParseClassSelector(aDataMask, *newSel);
   }
   else if (mToken.IsSymbol(':')) {    // :pseudo
     parsingStatus = ParsePseudoSelector(aDataMask, *newSel, PR_TRUE,
-                                        nsnull, nsnull, nsnull);
+                                        nsnull, nsnull);
   }
   else if (mToken.IsSymbol('[')) {    // [attribute
     parsingStatus = ParseAttributeSelector(aDataMask, *newSel);
   }
   else {
     // then it should be a type element or universal selector
     parsingStatus = ParseTypeOrUniversalSelector(aDataMask, *newSel, PR_TRUE);
   }
@@ -3290,18 +3262,17 @@ CSSParserImpl::ParseNegatedSimpleSelecto
   return eSelectorParsingStatus_Continue;
 }
 
 //
 // Parse the argument of a pseudo-class that has an ident arg
 //
 CSSParserImpl::nsSelectorParsingStatus
 CSSParserImpl::ParsePseudoClassWithIdentArg(nsCSSSelector& aSelector,
-                                            nsIAtom*       aPseudo,
-                                            nsCSSPseudoClasses::Type aType)
+                                            nsIAtom*       aPseudo)
 {
   // Check if we have the first parenthesis
   if (!ExpectSymbol('(', PR_FALSE)) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoArg);
     return eSelectorParsingStatus_Error;
   }
 
   if (! GetToken(PR_TRUE)) { // premature eof
@@ -3320,32 +3291,31 @@ CSSParserImpl::ParsePseudoClassWithIdent
   if (aPseudo == nsCSSPseudoClasses::mozLocaleDir) {
     if (!mToken.mIdent.EqualsLiteral("ltr") &&
         !mToken.mIdent.EqualsLiteral("rtl")) {
       return eSelectorParsingStatus_Error;
     }
   }
 
   // Add the pseudo with the language parameter
-  aSelector.AddPseudoClass(aPseudo, aType, mToken.mIdent.get());
+  aSelector.AddPseudoClass(aPseudo, mToken.mIdent.get());
 
   // close the parenthesis
   if (!ExpectSymbol(')', PR_TRUE)) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoClose);
     // XXX Call SkipUntil to the next ")"?
     return eSelectorParsingStatus_Error;
   }
 
   return eSelectorParsingStatus_Continue;
 }
 
 CSSParserImpl::nsSelectorParsingStatus
 CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
-                                              nsIAtom*       aPseudo,
-                                              nsCSSPseudoClasses::Type aType)
+                                              nsIAtom*       aPseudo)
 {
   PRInt32 numbers[2] = { 0, 0 };
   PRBool lookForB = PR_TRUE;
 
   // Check whether we have the first parenthesis
   if (!ExpectSymbol('(', PR_FALSE)) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoArg);
     return eSelectorParsingStatus_Error;
@@ -3458,30 +3428,29 @@ CSSParserImpl::ParsePseudoClassWithNthPa
       return eSelectorParsingStatus_Error;
     }
   }
   if (!mToken.IsSymbol(')')) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoClose);
     // XXX Call SkipUntil to the next ")"?
     return eSelectorParsingStatus_Error;
   }
-  aSelector.AddPseudoClass(aPseudo, aType, numbers);
+  aSelector.AddPseudoClass(aPseudo, numbers);
   return eSelectorParsingStatus_Continue;
 }
 
 
 /**
  * This is the format for selectors:
  * operator? [[namespace |]? element_name]? [ ID | class | attrib | pseudo ]*
  */
 CSSParserImpl::nsSelectorParsingStatus
 CSSParserImpl::ParseSelector(nsCSSSelector& aSelector,
                              nsIAtom** aPseudoElement,
-                             nsPseudoClassList** aPseudoElementArgs,
-                             nsCSSPseudoElements::Type* aPseudoElementType)
+                             nsPseudoClassList** aPseudoElementArgs)
 {
   if (! GetToken(PR_TRUE)) {
     REPORT_UNEXPECTED_EOF(PESelectorEOF);
     return eSelectorParsingStatus_Error;
   }
 
   PRInt32 dataMask = 0;
   nsSelectorParsingStatus parsingStatus =
@@ -3494,18 +3463,17 @@ CSSParserImpl::ParseSelector(nsCSSSelect
     if (eCSSToken_ID == mToken.mType) { // #id
       parsingStatus = ParseIDSelector(dataMask, aSelector);
     }
     else if (mToken.IsSymbol('.')) {    // .class
       parsingStatus = ParseClassSelector(dataMask, aSelector);
     }
     else if (mToken.IsSymbol(':')) {    // :pseudo
       parsingStatus = ParsePseudoSelector(dataMask, aSelector, PR_FALSE,
-                                          aPseudoElement, aPseudoElementArgs,
-                                          aPseudoElementType);
+                                          aPseudoElement, aPseudoElementArgs);
     }
     else if (mToken.IsSymbol('[')) {    // [attribute
       parsingStatus = ParseAttributeSelector(dataMask, aSelector);
     }
     else {  // not a selector token, we're done
       parsingStatus = eSelectorParsingStatus_Done;
       break;
     }
@@ -3907,18 +3875,17 @@ CSSParserImpl::ParseTreePseudoElement(ns
   nsCSSSelector fakeSelector; // so we can reuse AddPseudoClass
   if (ExpectSymbol('(', PR_FALSE)) {
     while (!ExpectSymbol(')', PR_TRUE)) {
       if (!GetToken(PR_TRUE)) {
         return PR_FALSE;
       }
       if (eCSSToken_Ident == mToken.mType) {
         nsCOMPtr<nsIAtom> pseudo = do_GetAtom(mToken.mIdent);
-        fakeSelector.AddPseudoClass(pseudo,
-                                    nsCSSPseudoClasses::ePseudoClass_NotPseudoClass);
+        fakeSelector.AddPseudoClass(pseudo);
       }
       else if (!mToken.IsSymbol(',')) {
         SkipUntil(')');
         return PR_FALSE;
       }
     }
     *aPseudoElementArgs = fakeSelector.mPseudoClassList;
     fakeSelector.mPseudoClassList = nsnull;
--- a/layout/style/nsCSSPseudoClassList.h
+++ b/layout/style/nsCSSPseudoClassList.h
@@ -37,88 +37,69 @@
  * ***** END LICENSE BLOCK ***** */
 
 /* atom list for CSS pseudo-classes */
 
 /*
  * This file contains the list of nsIAtoms and their values for CSS
  * pseudo-classes.  It is designed to be used as inline input to
  * nsCSSPseudoClasses.cpp *only* through the magic of C preprocessing.
- * All entries must be enclosed in the macros CSS_PSEUDO_CLASS or
- * CSS_STATE_PSEUDO_CLASS which will have cruel and unusual things
- * done to it.  The entries should be kept in some sort of logical
- * order.  The first argument to CSS_PSEUDO_CLASS is the C++
- * identifier of the atom.  The second argument is the string value of
- * the atom.  CSS_STATE_PSEUDO_CLASS also takes the name of the state
- * bit that the class corresponds to.  If CSS_STATE_PSEUDO_CLASS is
- * not defined, it'll be automatically defined to CSS_PSEUDO_CLASS.
+ * All entries must be enclosed in the macro CSS_PSEUDO_CLASS which will
+ * have cruel and unusual things done to it.  The entries should be kept
+ * in some sort of logical order.  The first argument to
+ * CSS_PSEUDO_CLASS is the C++ identifier of the atom.  The second
+ * argument is the string value of the atom.
  */
 
 // OUTPUT_CLASS=nsCSSPseudoClasses
 // MACRO_NAME=CSS_PSEUDO_CLASS
 
-#ifdef DEFINED_CSS_STATE_PSEUDO_CLASS
-#error "This shouldn't be defined"
-#endif
-
-#ifndef CSS_STATE_PSEUDO_CLASS
-#define CSS_STATE_PSEUDO_CLASS(_name, _value, _bit) \
-  CSS_PSEUDO_CLASS(_name, _value)
-#define DEFINED_CSS_STATE_PSEUDO_CLASS
-#endif
-
 CSS_PSEUDO_CLASS(empty, ":empty")
 CSS_PSEUDO_CLASS(mozOnlyWhitespace, ":-moz-only-whitespace")
 CSS_PSEUDO_CLASS(mozEmptyExceptChildrenWithLocalname, ":-moz-empty-except-children-with-localname")
 CSS_PSEUDO_CLASS(lang, ":lang")
 CSS_PSEUDO_CLASS(notPseudo, ":not")
 CSS_PSEUDO_CLASS(mozBoundElement, ":-moz-bound-element")
 CSS_PSEUDO_CLASS(root, ":root")
 
 CSS_PSEUDO_CLASS(link, ":link")
 CSS_PSEUDO_CLASS(mozAnyLink, ":-moz-any-link") // what matches :link or :visited
 CSS_PSEUDO_CLASS(visited, ":visited")
 
-CSS_STATE_PSEUDO_CLASS(active, ":active", NS_EVENT_STATE_ACTIVE)
-CSS_STATE_PSEUDO_CLASS(checked, ":checked", NS_EVENT_STATE_CHECKED)
-CSS_STATE_PSEUDO_CLASS(disabled, ":disabled", NS_EVENT_STATE_DISABLED)
-CSS_STATE_PSEUDO_CLASS(enabled, ":enabled", NS_EVENT_STATE_ENABLED)
-CSS_STATE_PSEUDO_CLASS(focus, ":focus", NS_EVENT_STATE_FOCUS)
-CSS_STATE_PSEUDO_CLASS(hover, ":hover", NS_EVENT_STATE_HOVER)
-CSS_STATE_PSEUDO_CLASS(mozDragOver, ":-moz-drag-over", NS_EVENT_STATE_DRAGOVER)
-CSS_STATE_PSEUDO_CLASS(target, ":target", NS_EVENT_STATE_URLTARGET)
-CSS_STATE_PSEUDO_CLASS(indeterminate, ":indeterminate",
-                       NS_EVENT_STATE_INDETERMINATE)
+CSS_PSEUDO_CLASS(active, ":active")
+CSS_PSEUDO_CLASS(checked, ":checked")
+CSS_PSEUDO_CLASS(disabled, ":disabled")
+CSS_PSEUDO_CLASS(enabled, ":enabled")
+CSS_PSEUDO_CLASS(focus, ":focus")
+CSS_PSEUDO_CLASS(hover, ":hover")
+CSS_PSEUDO_CLASS(mozDragOver, ":-moz-drag-over")
+CSS_PSEUDO_CLASS(target, ":target")
+CSS_PSEUDO_CLASS(indeterminate, ":indeterminate")
 
 CSS_PSEUDO_CLASS(firstChild, ":first-child")
 CSS_PSEUDO_CLASS(firstNode, ":-moz-first-node")
 CSS_PSEUDO_CLASS(lastChild, ":last-child")
 CSS_PSEUDO_CLASS(lastNode, ":-moz-last-node")
 CSS_PSEUDO_CLASS(onlyChild, ":only-child")
 CSS_PSEUDO_CLASS(firstOfType, ":first-of-type")
 CSS_PSEUDO_CLASS(lastOfType, ":last-of-type")
 CSS_PSEUDO_CLASS(onlyOfType, ":only-of-type")
 CSS_PSEUDO_CLASS(nthChild, ":nth-child")
 CSS_PSEUDO_CLASS(nthLastChild, ":nth-last-child")
 CSS_PSEUDO_CLASS(nthOfType, ":nth-of-type")
 CSS_PSEUDO_CLASS(nthLastOfType, ":nth-last-of-type")
 
 // Image, object, etc state pseudo-classes
-CSS_STATE_PSEUDO_CLASS(mozBroken, ":-moz-broken", NS_EVENT_STATE_BROKEN)
-CSS_STATE_PSEUDO_CLASS(mozUserDisabled, ":-moz-user-disabled",
-                       NS_EVENT_STATE_USERDISABLED)
-CSS_STATE_PSEUDO_CLASS(mozSuppressed, ":-moz-suppressed",
-                       NS_EVENT_STATE_SUPPRESSED)
-CSS_STATE_PSEUDO_CLASS(mozLoading, ":-moz-loading", NS_EVENT_STATE_LOADING)
-CSS_STATE_PSEUDO_CLASS(mozTypeUnsupported, ":-moz-type-unsupported",
-                       NS_EVENT_STATE_TYPE_UNSUPPORTED)
-CSS_STATE_PSEUDO_CLASS(mozHandlerDisabled, ":-moz-handler-disabled",
-                       NS_EVENT_STATE_HANDLER_DISABLED)
-CSS_STATE_PSEUDO_CLASS(mozHandlerBlocked, ":-moz-handler-blocked",
-                       NS_EVENT_STATE_HANDLER_BLOCKED)
+CSS_PSEUDO_CLASS(mozBroken, ":-moz-broken")
+CSS_PSEUDO_CLASS(mozUserDisabled, ":-moz-user-disabled")
+CSS_PSEUDO_CLASS(mozSuppressed, ":-moz-suppressed")
+CSS_PSEUDO_CLASS(mozLoading, ":-moz-loading")
+CSS_PSEUDO_CLASS(mozTypeUnsupported, ":-moz-type-unsupported")
+CSS_PSEUDO_CLASS(mozHandlerDisabled, ":-moz-handler-disabled")
+CSS_PSEUDO_CLASS(mozHandlerBlocked, ":-moz-handler-blocked")
 
 CSS_PSEUDO_CLASS(mozHasHandlerRef, ":-moz-has-handlerref")
 
 // Match nodes that are HTML but not XHTML
 CSS_PSEUDO_CLASS(mozIsHTML, ":-moz-is-html")
 
 // Matches anything when the specified look-and-feel metric is set
 CSS_PSEUDO_CLASS(mozSystemMetric, ":-moz-system-metric")
@@ -132,31 +113,22 @@ CSS_PSEUDO_CLASS(mozLWTheme, ":-moz-lwth
 
 // -moz-lwtheme-brighttext matches a document that has a bright lightweight theme
 CSS_PSEUDO_CLASS(mozLWThemeBrightText, ":-moz-lwtheme-brighttext")
 
 // -moz-lwtheme-darktext matches a document that has a bright lightweight theme
 CSS_PSEUDO_CLASS(mozLWThemeDarkText, ":-moz-lwtheme-darktext")
 
 #ifdef MOZ_MATHML
-CSS_STATE_PSEUDO_CLASS(mozMathIncrementScriptLevel,
-                       ":-moz-math-increment-script-level",
-                       NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL)
+CSS_PSEUDO_CLASS(mozMathIncrementScriptLevel, ":-moz-math-increment-script-level")
 #endif
 
 // CSS 3 UI
 // http://www.w3.org/TR/2004/CR-css3-ui-20040511/#pseudo-classes
-CSS_STATE_PSEUDO_CLASS(required, ":required", NS_EVENT_STATE_REQUIRED)
-CSS_STATE_PSEUDO_CLASS(optional, ":optional", NS_EVENT_STATE_OPTIONAL)
-CSS_STATE_PSEUDO_CLASS(valid, ":valid", NS_EVENT_STATE_VALID)
-CSS_STATE_PSEUDO_CLASS(invalid, ":invalid", NS_EVENT_STATE_INVALID)
-CSS_STATE_PSEUDO_CLASS(inRange, ":in-range", NS_EVENT_STATE_INRANGE)
-CSS_STATE_PSEUDO_CLASS(outOfRange, ":out-of-range", NS_EVENT_STATE_OUTOFRANGE)
-CSS_STATE_PSEUDO_CLASS(defaultPseudo, ":default", NS_EVENT_STATE_DEFAULT)
-CSS_STATE_PSEUDO_CLASS(mozReadOnly, ":-moz-read-only",
-                       NS_EVENT_STATE_MOZ_READONLY)
-CSS_STATE_PSEUDO_CLASS(mozReadWrite, ":-moz-read-write",
-                       NS_EVENT_STATE_MOZ_READWRITE)
-
-#ifdef DEFINED_CSS_STATE_PSEUDO_CLASS
-#undef DEFINED_CSS_STATE_PSEUDO_CLASS
-#undef CSS_STATE_PSEUDO_CLASS
-#endif
+CSS_PSEUDO_CLASS(required, ":required")
+CSS_PSEUDO_CLASS(optional, ":optional")
+CSS_PSEUDO_CLASS(valid, ":valid")
+CSS_PSEUDO_CLASS(invalid, ":invalid")
+CSS_PSEUDO_CLASS(inRange, ":in-range")
+CSS_PSEUDO_CLASS(outOfRange, ":out-of-range")
+CSS_PSEUDO_CLASS(defaultPseudo, ":default")
+CSS_PSEUDO_CLASS(mozReadOnly, ":-moz-read-only")
+CSS_PSEUDO_CLASS(mozReadWrite, ":-moz-read-write")
--- a/layout/style/nsCSSPseudoClasses.cpp
+++ b/layout/style/nsCSSPseudoClasses.cpp
@@ -80,20 +80,8 @@ nsCSSPseudoClasses::HasStringArg(nsIAtom
 PRBool
 nsCSSPseudoClasses::HasNthPairArg(nsIAtom* aAtom)
 {
   return aAtom == nsCSSPseudoClasses::nthChild ||
          aAtom == nsCSSPseudoClasses::nthLastChild ||
          aAtom == nsCSSPseudoClasses::nthOfType ||
          aAtom == nsCSSPseudoClasses::nthLastOfType;
 }
-
-nsCSSPseudoClasses::Type
-nsCSSPseudoClasses::GetPseudoType(nsIAtom* aAtom)
-{
-  for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(CSSPseudoClasses_info); ++i) {
-    if (*CSSPseudoClasses_info[i].mAtom == aAtom) {
-      return Type(i);
-    }
-  }
-
-  return nsCSSPseudoClasses::ePseudoClass_NotPseudoClass;
-}
--- a/layout/style/nsCSSPseudoClasses.h
+++ b/layout/style/nsCSSPseudoClasses.h
@@ -54,23 +54,11 @@ public:
 
   static PRBool IsPseudoClass(nsIAtom *aAtom);
   static PRBool HasStringArg(nsIAtom* aAtom);
   static PRBool HasNthPairArg(nsIAtom* aAtom);
 
 #define CSS_PSEUDO_CLASS(_name, _value) static nsICSSPseudoClass* _name;
 #include "nsCSSPseudoClassList.h"
 #undef CSS_PSEUDO_CLASS
-
-  enum Type {
-#define CSS_PSEUDO_CLASS(_name, _value) \
-    ePseudoClass_##_name,
-#include "nsCSSPseudoClassList.h"
-#undef CSS_PSEUDO_CLASS
-    ePseudoClass_Count,
-    ePseudoClass_NotPseudoClass /* This value MUST be last!  SelectorMatches
-                                   depends on it. */
-  };
-
-  static Type GetPseudoType(nsIAtom* aAtom);
 };
 
 #endif /* nsCSSPseudoClasses_h___ */
--- a/layout/style/nsCSSPseudoElementList.h
+++ b/layout/style/nsCSSPseudoElementList.h
@@ -66,23 +66,16 @@ CSS_PSEUDO_ELEMENT(firstLetter, ":first-
                    CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS)
 CSS_PSEUDO_ELEMENT(firstLine, ":first-line",
                    CSS_PSEUDO_ELEMENT_IS_CSS2 |
                    CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS)
 
 CSS_PSEUDO_ELEMENT(mozSelection, ":-moz-selection",
                    CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS)
 
-// XXXbz should we really allow random content to style these?  Maybe
-// use our flags to prevent that?
 CSS_PSEUDO_ELEMENT(mozFocusInner, ":-moz-focus-inner", 0)
 CSS_PSEUDO_ELEMENT(mozFocusOuter, ":-moz-focus-outer", 0)
 
-// XXXbz should we really allow random content to style these?  Maybe
-// use our flags to prevent that?
 CSS_PSEUDO_ELEMENT(mozListBullet, ":-moz-list-bullet", 0)
 CSS_PSEUDO_ELEMENT(mozListNumber, ":-moz-list-number", 0)
 
-#ifdef MOZ_MATHML
-CSS_PSEUDO_ELEMENT(mozMathStretchy, ":-moz-math-stretchy", 0)
-CSS_PSEUDO_ELEMENT(mozMathAnonymous, ":-moz-math-anonymous", 0)
-#endif
-
+CSS_PSEUDO_ELEMENT(horizontalFramesetBorder, ":-moz-hframeset-border", 0)
+CSS_PSEUDO_ELEMENT(verticalFramesetBorder, ":-moz-vframeset-border", 0)
--- a/layout/style/nsCSSPseudoElements.cpp
+++ b/layout/style/nsCSSPseudoElements.cpp
@@ -95,46 +95,16 @@ nsCSSPseudoElements::IsCSS2PseudoElement
                   aAtom == nsCSSPseudoElements::firstLine;
   NS_ASSERTION(nsCSSAnonBoxes::IsAnonBox(aAtom) ||
                result ==
                  PseudoElementHasFlags(aAtom, CSS_PSEUDO_ELEMENT_IS_CSS2),
                "result doesn't match flags");
   return result;
 }
 
-/* static */ nsCSSPseudoElements::Type
-nsCSSPseudoElements::GetPseudoType(nsIAtom *aAtom)
-{
-  for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(CSSPseudoElements_info); ++i) {
-    if (*CSSPseudoElements_info[i].mAtom == aAtom) {
-      return Type(i);
-    }
-  }
-
-  if (nsCSSAnonBoxes::IsAnonBox(aAtom)) {
-#ifdef MOZ_XUL
-    if (nsCSSAnonBoxes::IsTreePseudoElement(aAtom)) {
-      return ePseudo_XULTree;
-    }
-#endif
-
-    return ePseudo_AnonBox;
-  }
-
-  return ePseudo_NotPseudoElement;
-}
-
-/* static */ nsIAtom*
-nsCSSPseudoElements::GetPseudoAtom(Type aType)
-{
-  NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount,
-               "Unexpected type");
-  return *CSSPseudoElements_info[aType].mAtom;
-}
-
 /* static */ PRUint32
 nsCSSPseudoElements::FlagsForPseudoElement(nsIAtom *aAtom)
 {
   PRUint32 i;
   for (i = 0; i < NS_ARRAY_LENGTH(CSSPseudoElements_info); ++i) {
     if (*CSSPseudoElements_info[i].mAtom == aAtom) {
       break;
     }
--- a/layout/style/nsCSSPseudoElements.h
+++ b/layout/style/nsCSSPseudoElements.h
@@ -74,37 +74,16 @@ public:
     return PseudoElementHasFlags(aAtom, CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS);
   }
 
 #define CSS_PSEUDO_ELEMENT(_name, _value, _flags) \
   static nsICSSPseudoElement* _name;
 #include "nsCSSPseudoElementList.h"
 #undef CSS_PSEUDO_ELEMENT
 
-  enum Type {
-    // If the actual pseudo-elements stop being first here, change
-    // GetPseudoType.
-#define CSS_PSEUDO_ELEMENT(_name, _value_, _flags) \
-    ePseudo_##_name,
-#include "nsCSSPseudoElementList.h"
-#undef CSS_PSEUDO_ELEMENT
-    ePseudo_PseudoElementCount,
-    ePseudo_AnonBox = ePseudo_PseudoElementCount,
-#ifdef MOZ_XUL
-    ePseudo_XULTree,
-#endif
-    ePseudo_NotPseudoElement,
-    ePseudo_MAX
-  };
-
-  static Type GetPseudoType(nsIAtom* aAtom);
-
-  // Get the atom for a given Type.  aType must be < ePseudo_PseudoElementCount
-  static nsIAtom* GetPseudoAtom(Type aType);
-
 private:
   static PRUint32 FlagsForPseudoElement(nsIAtom *aAtom);
 
   // Does the given pseudo-element have all of the flags given?
   static PRBool PseudoElementHasFlags(nsIAtom *aAtom, PRUint32 aFlags)
   {
     return (FlagsForPseudoElement(aAtom) & aFlags) == aFlags;
   }
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -64,34 +64,32 @@
 #include "nsPresContext.h"
 #include "nsIEventStateManager.h"
 #include "nsGkAtoms.h"
 #include "nsString.h"
 #include "nsUnicharUtils.h"
 #include "nsDOMError.h"
 #include "nsRuleWalker.h"
 #include "nsCSSPseudoClasses.h"
-#include "nsCSSPseudoElements.h"
 #include "nsIContent.h"
 #include "nsCOMPtr.h"
 #include "nsHashKeys.h"
 #include "nsStyleUtil.h"
 #include "nsQuickSort.h"
 #include "nsAttrValue.h"
 #include "nsAttrName.h"
 #include "nsILookAndFeel.h"
 #include "nsWidgetsCID.h"
 #include "nsServiceManagerUtils.h"
 #include "nsTArray.h"
 #include "nsContentUtils.h"
 #include "nsIMediaList.h"
 #include "nsCSSRules.h"
 #include "nsIPrincipal.h"
 #include "nsStyleSet.h"
-#include "prlog.h"
 
 #define VISITED_PSEUDO_PREF "layout.css.visited_links_enabled"
 
 static PRBool gSupportVisitedPseudo = PR_TRUE;
 
 static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
 static nsTArray< nsCOMPtr<nsIAtom> >* sSystemMetrics = 0;
 
@@ -360,23 +358,25 @@ typedef void (*RuleEnumFunc)(nsICSSStyle
 
 class RuleHash {
 public:
   RuleHash(PRBool aQuirksMode);
   ~RuleHash();
   void PrependRule(RuleValue *aRuleInfo);
   void EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag, nsIAtom* aID,
                          const nsAttrValue* aClassList,
-                         RuleEnumFunc aFunc, RuleProcessorData* aData);
+                         RuleEnumFunc aFunc, void* aData);
+  void EnumerateTagRules(nsIAtom* aTag,
+                         RuleEnumFunc aFunc, void* aData);
   PLArenaPool& Arena() { return mArena; }
 
 protected:
   void PrependRuleToTable(PLDHashTable* aTable, const void* aKey,
                           RuleValue* aRuleInfo);
-  void PrependRuleToTagTable(nsIAtom* aKey, RuleValue* aRuleInfo);
+  void PrependRuleToTagTable(const void* aKey, RuleValue* aRuleInfo);
   void PrependUniversalRule(RuleValue* aRuleInfo);
 
   // All rule values in these hashtables are arena allocated
   PRInt32     mRuleCount;
   PLDHashTable mIdTable;
   PLDHashTable mClassTable;
   PLDHashTable mTagTable;
   PLDHashTable mNameSpaceTable;
@@ -390,45 +390,49 @@ protected:
 #ifdef RULE_HASH_STATS
   PRUint32    mUniversalSelectors;
   PRUint32    mNameSpaceSelectors;
   PRUint32    mTagSelectors;
   PRUint32    mClassSelectors;
   PRUint32    mIdSelectors;
 
   PRUint32    mElementsMatched;
+  PRUint32    mPseudosMatched;
 
   PRUint32    mElementUniversalCalls;
   PRUint32    mElementNameSpaceCalls;
   PRUint32    mElementTagCalls;
   PRUint32    mElementClassCalls;
   PRUint32    mElementIdCalls;
+
+  PRUint32    mPseudoTagCalls;
 #endif // RULE_HASH_STATS
 };
 
 RuleHash::RuleHash(PRBool aQuirksMode)
   : mRuleCount(0),
     mUniversalRules(nsnull),
     mEnumList(nsnull), mEnumListSize(0)
 #ifdef RULE_HASH_STATS
     ,
     mUniversalSelectors(0),
     mNameSpaceSelectors(0),
     mTagSelectors(0),
     mClassSelectors(0),
     mIdSelectors(0),
     mElementsMatched(0),
+    mPseudosMatched(0),
     mElementUniversalCalls(0),
     mElementNameSpaceCalls(0),
     mElementTagCalls(0),
     mElementClassCalls(0),
-    mElementIdCalls(0)
+    mElementIdCalls(0),
+    mPseudoTagCalls(0)
 #endif
 {
-  MOZ_COUNT_CTOR(RuleHash);
   // Initialize our arena
   PL_INIT_ARENA_POOL(&mArena, "RuleHashArena", NS_RULEHASH_ARENA_BLOCK_SIZE);
 
   PL_DHashTableInit(&mTagTable, &RuleHash_TagTable_Ops, nsnull,
                     sizeof(RuleHashTagTableEntry), 64);
   PL_DHashTableInit(&mIdTable,
                     aQuirksMode ? &RuleHash_IdTable_CIOps.ops
                                 : &RuleHash_IdTable_CSOps.ops,
@@ -438,29 +442,31 @@ RuleHash::RuleHash(PRBool aQuirksMode)
                                 : &RuleHash_ClassTable_CSOps.ops,
                     nsnull, sizeof(RuleHashTableEntry), 16);
   PL_DHashTableInit(&mNameSpaceTable, &RuleHash_NameSpaceTable_Ops, nsnull,
                     sizeof(RuleHashTableEntry), 16);
 }
 
 RuleHash::~RuleHash()
 {
-  MOZ_COUNT_DTOR(RuleHash);
 #ifdef RULE_HASH_STATS
   printf(
 "RuleHash(%p):\n"
 "  Selectors: Universal (%u) NameSpace(%u) Tag(%u) Class(%u) Id(%u)\n"
-"  Content Nodes: Elements(%u)\n"
+"  Content Nodes: Elements(%u) Pseudo-Elements(%u)\n"
 "  Element Calls: Universal(%u) NameSpace(%u) Tag(%u) Class(%u) Id(%u)\n"
+"  Pseudo-Element Calls: Tag(%u)\n",
          static_cast<void*>(this),
          mUniversalSelectors, mNameSpaceSelectors, mTagSelectors,
            mClassSelectors, mIdSelectors,
          mElementsMatched,
+         mPseudosMatched,
          mElementUniversalCalls, mElementNameSpaceCalls, mElementTagCalls,
-           mElementClassCalls, mElementIdCalls);
+           mElementClassCalls, mElementIdCalls,
+         mPseudoTagCalls);
 #ifdef PRINT_UNIVERSAL_RULES
   {
     RuleValue* value = mUniversalRules;
     if (value) {
       printf("  Universal rules:\n");
       do {
         nsAutoString selectorText;
         PRUint32 lineNumber = value->mRule->GetLineNumber();
@@ -497,36 +503,29 @@ void RuleHash::PrependRuleToTable(PLDHas
   // Get a new or existing entry.
   RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                          (PL_DHashTableOperate(aTable, aKey, PL_DHASH_ADD));
   if (!entry)
     return;
   entry->mRules = aRuleInfo->Add(mRuleCount++, entry->mRules);
 }
 
-static void
-DoPrependRuleToTagTable(PLDHashTable* aTable, nsIAtom* aKey,
-                        RuleValue* aRuleInfo, PRInt32 aBackwardsIndex)
+void RuleHash::PrependRuleToTagTable(const void* aKey, RuleValue* aRuleInfo)
 {
   // Get a new or exisiting entry
-  RuleHashTagTableEntry *entry = static_cast<RuleHashTagTableEntry*>
-    (PL_DHashTableOperate(aTable, aKey, PL_DHASH_ADD));
-  if (!entry)
-    return;
-
-  entry->mTag = aKey;
+   RuleHashTagTableEntry *entry = static_cast<RuleHashTagTableEntry*>
+                              (PL_DHashTableOperate(&mTagTable, aKey, PL_DHASH_ADD));
+   if (!entry)
+     return;
 
-  // This may give the same rule two different rule counts, but that is OK
-  // because we never combine two different entries in a tag table.
-  entry->mRules = aRuleInfo->Add(aBackwardsIndex, entry->mRules);
-}
+   entry->mTag = const_cast<nsIAtom*>(static_cast<const nsIAtom*>(aKey));
 
-void RuleHash::PrependRuleToTagTable(nsIAtom* aKey, RuleValue* aRuleInfo)
-{
-  DoPrependRuleToTagTable(&mTagTable, aKey, aRuleInfo, mRuleCount++);
+   // This may give the same rule two different rule counts, but that is OK
+   // because we never combine two different entries in the tag table.
+   entry->mRules = aRuleInfo->Add(mRuleCount++, entry->mRules);
 }
 
 void RuleHash::PrependUniversalRule(RuleValue *aRuleInfo)
 {
   mUniversalRules = aRuleInfo->Add(mRuleCount++, mUniversalRules);
 }
 
 void RuleHash::PrependRule(RuleValue *aRuleInfo)
@@ -570,17 +569,17 @@ void RuleHash::PrependRule(RuleValue *aR
   do { ++(var_); (list_) = (list_)->mNext; } while (list_)
 #else
 #define RULE_HASH_STAT_INCREMENT_LIST_COUNT(list_, var_) \
   PR_BEGIN_MACRO PR_END_MACRO
 #endif
 
 void RuleHash::EnumerateAllRules(PRInt32 aNameSpace, nsIAtom* aTag,
                                  nsIAtom* aID, const nsAttrValue* aClassList,
-                                 RuleEnumFunc aFunc, RuleProcessorData* aData)
+                                 RuleEnumFunc aFunc, void* aData)
 {
   PRInt32 classCount = aClassList ? aClassList->GetAtomCount() : 0;
 
   // assume 1 universal, tag, id, and namespace, rather than wasting
   // time counting
   PRInt32 testCount = classCount + 4;
 
   if (mEnumListSize < testCount) {
@@ -595,45 +594,45 @@ void RuleHash::EnumerateAllRules(PRInt32
   { // universal rules
     RuleValue* value = mUniversalRules;
     if (nsnull != value) {
       mEnumList[valueCount++] = value;
       RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementUniversalCalls);
     }
   }
   // universal rules within the namespace
-  if (kNameSpaceID_Unknown != aNameSpace && mNameSpaceTable.entryCount) {
+  if (kNameSpaceID_Unknown != aNameSpace) {
     RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                            (PL_DHashTableOperate(&mNameSpaceTable, NS_INT32_TO_PTR(aNameSpace),
                              PL_DHASH_LOOKUP));
     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
       RuleValue *value = entry->mRules;
       mEnumList[valueCount++] = value;
       RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementNameSpaceCalls);
     }
   }
-  if (aTag && mTagTable.entryCount) {
+  if (nsnull != aTag) {
     RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                            (PL_DHashTableOperate(&mTagTable, aTag, PL_DHASH_LOOKUP));
     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
       RuleValue *value = entry->mRules;
       mEnumList[valueCount++] = value;
       RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementTagCalls);
     }
   }
-  if (aID && mIdTable.entryCount) {
+  if (nsnull != aID) {
     RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                            (PL_DHashTableOperate(&mIdTable, aID, PL_DHASH_LOOKUP));
     if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
       RuleValue *value = entry->mRules;
       mEnumList[valueCount++] = value;
       RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementIdCalls);
     }
   }
-  if (mClassTable.entryCount) {
+  { // extra scope to work around compiler bugs with |for| scoping.
     for (PRInt32 index = 0; index < classCount; ++index) {
       RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
                                              (PL_DHashTableOperate(&mClassTable, aClassList->AtomAt(index),
                              PL_DHASH_LOOKUP));
       if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
         RuleValue *value = entry->mRules;
         mEnumList[valueCount++] = value;
         RULE_HASH_STAT_INCREMENT_LIST_COUNT(value, mElementClassCalls);
@@ -664,16 +663,32 @@ void RuleHash::EnumerateAllRules(PRInt32
     RuleValue* value = mEnumList[0];
     do {
       (*aFunc)(value->mRule, value->mSelector, aData);
       value = value->mNext;
     } while (value);
   }
 }
 
+void RuleHash::EnumerateTagRules(nsIAtom* aTag, RuleEnumFunc aFunc, void* aData)
+{
+  RuleHashTableEntry *entry = static_cast<RuleHashTableEntry*>
+                                         (PL_DHashTableOperate(&mTagTable, aTag, PL_DHASH_LOOKUP));
+
+  RULE_HASH_STAT_INCREMENT(mPseudosMatched);
+  if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
+    RuleValue *tagValue = entry->mRules;
+    do {
+      RULE_HASH_STAT_INCREMENT(mPseudoTagCalls);
+      (*aFunc)(tagValue->mRule, tagValue->mSelector, aData);
+      tagValue = tagValue->mNext;
+    } while (tagValue);
+  }
+}
+
 //--------------------------------
 
 // Attribute selectors hash table.
 struct AttributeSelectorEntry : public PLDHashEntryHdr {
   nsIAtom *mAttribute;
   nsTArray<nsCSSSelector*> *mSelectors;
 };
 
@@ -699,61 +714,40 @@ static const PLDHashTableOps AttributeSe
 
 //--------------------------------
 
 struct RuleCascadeData {
   RuleCascadeData(nsIAtom *aMedium, PRBool aQuirksMode)
     : mRuleHash(aQuirksMode),
       mStateSelectors(),
       mCacheKey(aMedium),
-      mNext(nsnull),
-      mQuirksMode(aQuirksMode)
+      mNext(nsnull)
   {
     PL_DHashTableInit(&mAttributeSelectors, &AttributeSelectorOps, nsnull,
                       sizeof(AttributeSelectorEntry), 16);
-    PL_DHashTableInit(&mAnonBoxRules, &RuleHash_TagTable_Ops, nsnull,
-                      sizeof(RuleHashTagTableEntry), 16);
-    memset(mPseudoElementRuleHashes, 0, sizeof(mPseudoElementRuleHashes));
-#ifdef MOZ_XUL
-    PL_DHashTableInit(&mXULTreeRules, &RuleHash_TagTable_Ops, nsnull,
-                      sizeof(RuleHashTagTableEntry), 16);
-#endif
   }
 
   ~RuleCascadeData()
   {
     PL_DHashTableFinish(&mAttributeSelectors);
-    PL_DHashTableFinish(&mAnonBoxRules);
-    PL_DHashTableFinish(&mXULTreeRules);
-    for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(mPseudoElementRuleHashes); ++i) {
-      delete mPseudoElementRuleHashes[i];
-    }
   }
   RuleHash                 mRuleHash;
-  RuleHash*
-    mPseudoElementRuleHashes[nsCSSPseudoElements::ePseudo_PseudoElementCount];
   nsTArray<nsCSSSelector*> mStateSelectors;
   nsTArray<nsCSSSelector*> mClassSelectors;
   nsTArray<nsCSSSelector*> mIDSelectors;
   PLDHashTable             mAttributeSelectors;
-  PLDHashTable             mAnonBoxRules;
-#ifdef MOZ_XUL
-  PLDHashTable             mXULTreeRules;
-#endif
 
   nsTArray<nsFontFaceRuleContainer> mFontFaceRules;
 
   // Looks up or creates the appropriate list in |mAttributeSelectors|.
   // Returns null only on allocation failure.
   nsTArray<nsCSSSelector*>* AttributeListFor(nsIAtom* aAttribute);
 
   nsMediaQueryResultCacheKey mCacheKey;
   RuleCascadeData*  mNext; // for a different medium
-
-  const PRBool mQuirksMode;
 };
 
 nsTArray<nsCSSSelector*>*
 RuleCascadeData::AttributeListFor(nsIAtom* aAttribute)
 {
   AttributeSelectorEntry *entry = static_cast<AttributeSelectorEntry*>
                                              (PL_DHashTableOperate(&mAttributeSelectors, aAttribute, PL_DHASH_ADD));
   if (!entry)
@@ -910,17 +904,17 @@ RuleProcessorData::RuleProcessorData(nsP
     mPreviousSiblingData(nsnull),
     mParentData(nsnull),
     mLanguage(nsnull),
     mGotContentState(PR_FALSE),
     mGotLinkInfo(PR_FALSE)
 {
   MOZ_COUNT_CTOR(RuleProcessorData);
 
-  NS_ASSERTION(aContent && aContent->IsNodeOfType(nsINode::eELEMENT),
+  NS_ASSERTION(!aContent || aContent->IsNodeOfType(nsINode::eELEMENT),
                "non-element leaked into SelectorMatches");
 
   mNthIndices[0][0] = -2;
   mNthIndices[0][1] = -2;
   mNthIndices[1][0] = -2;
   mNthIndices[1][1] = -2;
 
   // get the compat. mode (unless it is provided)
@@ -930,40 +924,51 @@ RuleProcessorData::RuleProcessorData(nsP
   } else if (NS_LIKELY(mPresContext)) {
     mCompatMode = mPresContext->CompatibilityMode();
   } else {
     NS_ASSERTION(aContent, "Must have content");
     NS_ASSERTION(aContent->GetOwnerDoc(), "Must have document");
     mCompatMode = aContent->GetOwnerDoc()->GetCompatibilityMode();
   }
 
-  NS_ASSERTION(aContent->GetOwnerDoc(), "Document-less node here?");
+  if (NS_LIKELY(aContent)) {
+    NS_ASSERTION(aContent->GetOwnerDoc(), "Document-less node here?");
     
-  // get the tag and parent
-  mContentTag = aContent->Tag();
-  mParentContent = aContent->GetParent();
+    // get the tag and parent
+    mContentTag = aContent->Tag();
+    mParentContent = aContent->GetParent();
 
-  // see if there are attributes for the content
-  mHasAttributes = aContent->GetAttrCount() > 0;
-  if (mHasAttributes) {
-    // get the ID and classes for the content
-    mContentID = aContent->GetID();
-    mClasses = aContent->GetClasses();
+    // see if there are attributes for the content
+    mHasAttributes = aContent->GetAttrCount() > 0;
+    if (mHasAttributes) {
+      // get the ID and classes for the content
+      mContentID = aContent->GetID();
+      mClasses = aContent->GetClasses();
+    } else {
+      mContentID = nsnull;
+      mClasses = nsnull;
+    }
+
+    // get the namespace
+    mNameSpaceID = aContent->GetNameSpaceID();
+
+    // check for HTMLContent status
+    mIsHTMLContent = (mNameSpaceID == kNameSpaceID_XHTML);
+    mIsHTML = mIsHTMLContent && aContent->IsInHTMLDocument();
   } else {
+    mContentTag = nsnull;
+    mParentContent = nsnull;
     mContentID = nsnull;
     mClasses = nsnull;
+    mHasAttributes = PR_FALSE;
+    mNameSpaceID = kNameSpaceID_Unknown;
+    mIsHTMLContent = PR_FALSE;
+    mIsHTML = PR_FALSE;
   }
 
-  // get the namespace
-  mNameSpaceID = aContent->GetNameSpaceID();
-
-  // check for HTMLContent status
-  mIsHTMLContent = (mNameSpaceID == kNameSpaceID_XHTML);
-  mIsHTML = mIsHTMLContent && aContent->IsInHTMLDocument();
-
   // No need to initialize mIsLink or mLinkState; the IsLink() accessor will
   // handle that.
 
   // No need to initialize mContentState; the ContentState() accessor will handle
   // that.
 }
 
 RuleProcessorData::~RuleProcessorData()
@@ -1027,57 +1032,61 @@ const nsString* RuleProcessorData::GetLa
 }
 
 PRUint32
 RuleProcessorData::ContentState()
 {
   if (!mGotContentState) {
     mGotContentState = PR_TRUE;
     mContentState = 0;
-    if (mPresContext) {
-      mPresContext->EventStateManager()->GetContentState(mContent,
-                                                         mContentState);
-    } else {
-      mContentState = mContent->IntrinsicState();
+    if (mContent) {
+      if (mPresContext) {
+        mPresContext->EventStateManager()->GetContentState(mContent,
+                                                           mContentState);
+      } else {
+        mContentState = mContent->IntrinsicState();
+      }
     }
   }
   return mContentState;
 }
 
 PRBool
 RuleProcessorData::IsLink()
 {
   if (!mGotLinkInfo) {
     mGotLinkInfo = PR_TRUE;
     mLinkState = eLinkState_Unknown;
     mIsLink = PR_FALSE;
-    // if HTML content and it has some attributes, check for an HTML link
-    // NOTE: optimization: cannot be a link if no attributes (since it needs
-    // an href)
-    nsILinkHandler* linkHandler =
-      mPresContext ? mPresContext->GetLinkHandler() : nsnull;
-    if (mIsHTMLContent && mHasAttributes) {
-      // check if it is an HTML Link
-      if (nsStyleUtil::IsHTMLLink(mContent, linkHandler, &mLinkState)) {
+    if (mContent) {
+      // if HTML content and it has some attributes, check for an HTML link
+      // NOTE: optimization: cannot be a link if no attributes (since it needs
+      // an href)
+      nsILinkHandler* linkHandler =
+        mPresContext ? mPresContext->GetLinkHandler() : nsnull;
+      if (mIsHTMLContent && mHasAttributes) {
+        // check if it is an HTML Link
+        if (nsStyleUtil::IsHTMLLink(mContent, linkHandler, &mLinkState)) {
+          mIsLink = PR_TRUE;
+        }
+      }
+
+      // if not an HTML link, check for a simple xlink (cannot be both HTML
+      // link and xlink) NOTE: optimization: cannot be an XLink if no
+      // attributes (since it needs an href)
+      if(!mIsLink &&
+         mHasAttributes && 
+         !(mIsHTMLContent || mContent->IsXUL()) && 
+         nsStyleUtil::IsLink(mContent, linkHandler, &mLinkState)) {
         mIsLink = PR_TRUE;
       }
-    }
 
-    // if not an HTML link, check for a simple xlink (cannot be both HTML
-    // link and xlink) NOTE: optimization: cannot be an XLink if no
-    // attributes (since it needs an href)
-    if(!mIsLink &&
-       mHasAttributes && 
-       !(mIsHTMLContent || mContent->IsXUL()) && 
-       nsStyleUtil::IsLink(mContent, linkHandler, &mLinkState)) {
-      mIsLink = PR_TRUE;
-    }
-
-    if (mLinkState == eLinkState_Visited && !gSupportVisitedPseudo) {
-      mLinkState = eLinkState_Unvisited;
+      if (mLinkState == eLinkState_Visited && !gSupportVisitedPseudo) {
+        mLinkState = eLinkState_Unvisited;
+      }
     }
   }
   return mIsLink;
 }
 
 PRInt32
 RuleProcessorData::GetNthIndex(PRBool aIsOfType, PRBool aIsFromEnd,
                                PRBool aCheckEdgeOnly)
@@ -1179,16 +1188,23 @@ static PRBool ValueIncludes(const nsSubs
         aValue.Equals(Substring(val_start, val_end), aComparator))
       return PR_TRUE;
 
     ++p; // we know the next character is not whitespace
   }
   return PR_FALSE;
 }
 
+inline PRBool IsLinkPseudo(nsIAtom* aAtom)
+{
+  return PRBool ((nsCSSPseudoClasses::link == aAtom) || 
+                 (nsCSSPseudoClasses::visited == aAtom) ||
+                 (nsCSSPseudoClasses::mozAnyLink == aAtom));
+}
+
 // Return whether we should apply a "global" (i.e., universal-tag)
 // selector for event states in quirks mode.  Note that
 // |data.IsLink()| is checked separately by the caller, so we return
 // false for |nsGkAtoms::a|, which here means a named anchor.
 inline PRBool IsQuirkEventSensitive(nsIAtom *aContentTag)
 {
   return PRBool ((nsGkAtoms::button == aContentTag) ||
                  (nsGkAtoms::img == aContentTag)    ||
@@ -1246,525 +1262,16 @@ static PRBool AttrMatchesValue(const nsA
     case NS_ATTR_FUNC_CONTAINSMATCH:
       return FindInReadable(aAttrSelector->mValue, aValue, comparator);
     default:
       NS_NOTREACHED("Shouldn't be ending up here");
       return PR_FALSE;
   }
 }
 
-static PRBool NS_FASTCALL
-firstNodeMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                 nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::firstNode,
-                  "Unexpected atom");
-  nsIContent *firstNode = nsnull;
-  nsIContent *parent = data.mParentContent;
-  if (parent) {
-    if (setNodeFlags)
-      parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
-
-    PRInt32 index = -1;
-    do {
-      firstNode = parent->GetChildAt(++index);
-      // stop at first non-comment and non-whitespace node
-    } while (firstNode &&
-             !IsSignificantChild(firstNode, PR_TRUE, PR_FALSE));
-  }
-  return (data.mContent == firstNode);
-}
-
-static PRBool NS_FASTCALL
-lastNodeMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::lastNode,
-                  "Unexpected atom");
-  nsIContent *lastNode = nsnull;
-  nsIContent *parent = data.mParentContent;
-  if (parent) {
-    if (setNodeFlags)
-      parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
-
-    PRUint32 index = parent->GetChildCount();
-    do {
-      lastNode = parent->GetChildAt(--index);
-      // stop at first non-comment and non-whitespace node
-    } while (lastNode &&
-             !IsSignificantChild(lastNode, PR_TRUE, PR_FALSE));
-  }
-  return (data.mContent == lastNode);
-}
-
-static inline PRBool
-edgeChildMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                 PRBool checkFirst, PRBool checkLast)
-{
-  nsIContent *parent = data.mParentContent;
-  if (!parent) {
-    return PR_FALSE;
-  }
-
-  if (setNodeFlags)
-    parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
-
-  return (!checkFirst ||
-          data.GetNthIndex(PR_FALSE, PR_FALSE, PR_TRUE) == 1) &&
-         (!checkLast ||
-          data.GetNthIndex(PR_FALSE, PR_TRUE, PR_TRUE) == 1);
-}
-
-static PRBool NS_FASTCALL
-firstChildMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                  nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::firstChild,
-                  "Unexpected atom");
-  return edgeChildMatches(data, setNodeFlags, PR_TRUE, PR_FALSE);
-}
-
-static PRBool NS_FASTCALL
-lastChildMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                 nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::lastChild,
-                  "Unexpected atom");
-  return edgeChildMatches(data, setNodeFlags, PR_FALSE, PR_TRUE);
-}
-
-static PRBool NS_FASTCALL
-onlyChildMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                 nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::onlyChild,
-                  "Unexpected atom");
-  return edgeChildMatches(data, setNodeFlags, PR_TRUE, PR_TRUE);
-}
-
-static inline PRBool
-nthChildGenericMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                       nsPseudoClassList* pseudoClass,
-                       PRBool isOfType, PRBool isFromEnd)
-{
-  nsIContent *parent = data.mParentContent;
-  if (!parent) {
-    return PR_FALSE;
-  }
-
-  if (setNodeFlags) {
-    if (isFromEnd)
-      parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
-    else
-      parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
-  }
-
-  const PRInt32 index = data.GetNthIndex(isOfType, isFromEnd, PR_FALSE);
-  if (index <= 0) {
-    // Node is anonymous content (not really a child of its parent).
-    return PR_FALSE;
-  }
-
-  const PRInt32 a = pseudoClass->u.mNumbers[0];
-  const PRInt32 b = pseudoClass->u.mNumbers[1];
-  // result should be true if there exists n >= 0 such that
-  // a * n + b == index.
-  if (a == 0) {
-    return b == index;
-  }
-
-  // Integer division in C does truncation (towards 0).  So
-  // check that the result is nonnegative, and that there was no
-  // truncation.
-  const PRInt32 n = (index - b) / a;
-  return n >= 0 && (a * n == index - b);
-}
-
-static PRBool NS_FASTCALL
-nthChildMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::nthChild,
-                  "Unexpected atom");
-  return nthChildGenericMatches(data, setNodeFlags, pseudoClass,
-                                PR_FALSE, PR_FALSE);
-}
-
-static PRBool NS_FASTCALL
-nthLastChildMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                    nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::nthLastChild,
-                  "Unexpected atom");
-  return nthChildGenericMatches(data, setNodeFlags, pseudoClass,
-                                PR_FALSE, PR_TRUE);
-}
-
-static PRBool NS_FASTCALL
-nthOfTypeMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                 nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::nthOfType,
-                  "Unexpected atom");
-  return nthChildGenericMatches(data, setNodeFlags, pseudoClass,
-                                PR_TRUE, PR_FALSE);
-}
-
-static PRBool NS_FASTCALL
-nthLastOfTypeMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                     nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::nthLastOfType,
-                  "Unexpected atom");
-  return nthChildGenericMatches(data, setNodeFlags, pseudoClass,
-                                PR_TRUE, PR_TRUE);
-}
-
-static inline PRBool
-edgeOfTypeMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                  PRBool checkFirst, PRBool checkLast)
-{
-  nsIContent *parent = data.mParentContent;
-  if (!parent) {
-    return PR_FALSE;
-  }
-
-  if (setNodeFlags) {
-    if (checkLast)
-      parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
-    else
-      parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
-  }
-
-  return (!checkFirst ||
-          data.GetNthIndex(PR_TRUE, PR_FALSE, PR_TRUE) == 1) &&
-         (!checkLast ||
-          data.GetNthIndex(PR_TRUE, PR_TRUE, PR_TRUE) == 1);
-}
-
-static PRBool NS_FASTCALL
-firstOfTypeMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                   nsPseudoClassList* pseudoClass)
-{ 
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::firstOfType,
-                  "Unexpected atom");
-  return edgeOfTypeMatches(data, setNodeFlags, PR_TRUE, PR_FALSE);
-}
-
-static PRBool NS_FASTCALL
-lastOfTypeMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                  nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::lastOfType,
-                  "Unexpected atom");
-  return edgeOfTypeMatches(data, setNodeFlags, PR_FALSE, PR_TRUE);
-}
-
-static PRBool NS_FASTCALL
-onlyOfTypeMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                  nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::onlyOfType,
-                  "Unexpected atom");
-  return edgeOfTypeMatches(data, setNodeFlags, PR_TRUE, PR_TRUE);
-}
-
-static inline PRBool
-checkGenericEmptyMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                         PRBool isWhitespaceSignificant)
-{
-  nsIContent *child = nsnull;
-  nsIContent *element = data.mContent;
-  PRInt32 index = -1;
-
-  if (setNodeFlags)
-    element->SetFlags(NODE_HAS_EMPTY_SELECTOR);
-
-  do {
-    child = element->GetChildAt(++index);
-    // stop at first non-comment (and non-whitespace for
-    // :-moz-only-whitespace) node        
-  } while (child && !IsSignificantChild(child, PR_TRUE, isWhitespaceSignificant));
-  return (child == nsnull);
-}
-
-static PRBool NS_FASTCALL
-emptyMatches(RuleProcessorData& data, PRBool setNodeFlags,
-             nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::empty,
-                  "Unexpected atom");
-  return checkGenericEmptyMatches(data, setNodeFlags, PR_TRUE);
-}
-
-static PRBool NS_FASTCALL
-mozOnlyWhitespaceMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                         nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::mozOnlyWhitespace,
-                  "Unexpected atom");
-  return checkGenericEmptyMatches(data, setNodeFlags, PR_FALSE);
-}
-
-static PRBool NS_FASTCALL
-mozEmptyExceptChildrenWithLocalnameMatches(RuleProcessorData& data,
-                                           PRBool setNodeFlags,
-                                           nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom ==
-                    nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname,
-                  "Unexpected atom");
-  NS_ASSERTION(pseudoClass->u.mString, "Must have string!");
-  nsIContent *child = nsnull;
-  nsIContent *element = data.mContent;
-  PRInt32 index = -1;
-
-  if (setNodeFlags)
-    element->SetFlags(NODE_HAS_SLOW_SELECTOR);
-
-  do {
-    child = element->GetChildAt(++index);
-  } while (child &&
-           (!IsSignificantChild(child, PR_TRUE, PR_FALSE) ||
-            (child->GetNameSpaceID() == element->GetNameSpaceID() &&
-             child->Tag()->Equals(nsDependentString(pseudoClass->u.mString)))));
-  return (child == nsnull);
-}
-
-static PRBool NS_FASTCALL
-mozSystemMetricMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                       nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::mozSystemMetric,
-                  "Unexpected atom");
-  NS_ASSERTION(pseudoClass->u.mString, "Must have string!");
-  nsCOMPtr<nsIAtom> metric = do_GetAtom(pseudoClass->u.mString);
-  return nsCSSRuleProcessor::HasSystemMetric(metric);
-}
-
-static PRBool NS_FASTCALL
-mozHasHandlerRefMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                        nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::mozHasHandlerRef,
-                  "Unexpected atom");
-  nsIContent *child = nsnull;
-  nsIContent *element = data.mContent;
-  PRInt32 index = -1;
-
-  do {
-    child = element->GetChildAt(++index);
-    if (child && child->IsHTML() &&
-        child->Tag() == nsGkAtoms::param &&
-        child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
-                           NS_LITERAL_STRING("pluginurl"), eIgnoreCase)) {
-      return PR_TRUE;
-    }
-  } while (child);
-  return PR_FALSE;
-}
-
-static PRBool NS_FASTCALL
-rootMatches(RuleProcessorData& data, PRBool setNodeFlags,
-            nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::root,
-                  "Unexpected atom");
-  return (data.mParentContent == nsnull &&
-          data.mContent == data.mContent->GetOwnerDoc()->GetRootContent());
-}
-
-static PRBool NS_FASTCALL
-mozBoundElementMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                       nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::mozBoundElement,
-                  "Unexpected atom");
-  // XXXldb How do we know where the selector came from?  And what
-  // if there are multiple bindings, and we should be matching the
-  // outer one?
-  return (data.mScopedRoot == data.mContent);
-}
-
-static PRBool NS_FASTCALL
-langMatches(RuleProcessorData& data, PRBool setNodeFlags,
-            nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::lang,
-                  "Unexpected atom");
-  NS_ASSERTION(nsnull != pseudoClass->u.mString, "null lang parameter");
-  if (!pseudoClass->u.mString || !*pseudoClass->u.mString) {
-    return PR_FALSE;
-  }
-
-  // We have to determine the language of the current element.  Since
-  // this is currently no property and since the language is inherited
-  // from the parent we have to be prepared to look at all parent
-  // nodes.  The language itself is encoded in the LANG attribute.
-  const nsString* lang = data.GetLang();
-  if (lang && !lang->IsEmpty()) { // null check for out-of-memory
-    return
-      nsStyleUtil::DashMatchCompare(*lang,
-                                    nsDependentString(pseudoClass->u.mString), 
-                                    nsCaseInsensitiveStringComparator());
-  }
-
-  nsIDocument* doc = data.mContent->GetDocument();
-  if (doc) {
-    // Try to get the language from the HTTP header or if this
-    // is missing as well from the preferences.
-    // The content language can be a comma-separated list of
-    // language codes.
-    nsAutoString language;
-    doc->GetContentLanguage(language);
-
-    nsDependentString langString(pseudoClass->u.mString);
-    language.StripWhitespace();
-    PRInt32 begin = 0;
-    PRInt32 len = language.Length();
-    while (begin < len) {
-      PRInt32 end = language.FindChar(PRUnichar(','), begin);
-      if (end == kNotFound) {
-        end = len;
-      }
-      if (nsStyleUtil::DashMatchCompare(Substring(language, begin, end-begin),
-                                        langString,
-                                        nsCaseInsensitiveStringComparator())) {
-        return PR_TRUE;
-      }
-      begin = end + 1;
-    }
-  }
-
-  return PR_FALSE;
-}
-
-static PRBool NS_FASTCALL
-mozAnyLinkMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                  nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::mozAnyLink,
-                  "Unexpected atom");
-  return data.IsLink();
-}
-
-static PRBool NS_FASTCALL
-linkMatches(RuleProcessorData& data, PRBool setNodeFlags,
-            nsPseudoClassList* pseudoClass)
-{
-  NS_NOTREACHED("Shouldn't be called");
-  return PR_FALSE;
-}
-
-static PRBool NS_FASTCALL
-visitedMatches(RuleProcessorData& data, PRBool setNodeFlags,
-               nsPseudoClassList* pseudoClass)
-{
-  NS_NOTREACHED("Shouldn't be called");
-  return PR_FALSE;
-}
-
-static PRBool NS_FASTCALL
-mozIsHTMLMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                 nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::mozIsHTML,
-                  "Unexpected atom");
-  return data.mIsHTML;
-}
-
-static PRBool NS_FASTCALL
-mozLocaleDirMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                    nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::mozLocaleDir,
-                  "Unexpected atom");
-  nsIDocument* doc = data.mContent->GetDocument();
-
-  if (!doc) {
-    return PR_FALSE;
-  }
-
-  PRBool docIsRTL = doc && doc->IsDocumentRightToLeft();
-
-  nsDependentString dirString(pseudoClass->u.mString);
-  NS_ASSERTION(dirString.EqualsLiteral("ltr") || dirString.EqualsLiteral("rtl"),
-               "invalid value for -moz-locale-dir");
-
-  return dirString.EqualsLiteral("rtl") == docIsRTL;
-}
-
-static PRBool NS_FASTCALL
-mozLWThemeMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                  nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom == nsCSSPseudoClasses::mozLWTheme,
-                  "Unexpected atom");
-  nsIDocument* doc = data.mContent->GetOwnerDoc();
-  return doc && doc->GetDocumentLWTheme() > nsIDocument::Doc_Theme_None;
-}
-
-static PRBool NS_FASTCALL
-mozLWThemeBrightTextMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                            nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom ==
-                    nsCSSPseudoClasses::mozLWThemeBrightText,
-                  "Unexpected atom");
-  nsIDocument* doc = data.mContent->GetOwnerDoc();
-  return doc && doc->GetDocumentLWTheme() == nsIDocument::Doc_Theme_Bright;
-}
-
-static PRBool NS_FASTCALL
-mozLWThemeDarkTextMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                          nsPseudoClassList* pseudoClass)
-{
-  NS_PRECONDITION(pseudoClass->mAtom ==
-                    nsCSSPseudoClasses::mozLWThemeDarkText,
-                  "Unexpected atom");
-  nsIDocument* doc = data.mContent->GetOwnerDoc();
-  return doc && doc->GetDocumentLWTheme() == nsIDocument::Doc_Theme_Dark;
-}
-
-static PRBool NS_FASTCALL
-notPseudoMatches(RuleProcessorData& data, PRBool setNodeFlags,
-                 nsPseudoClassList* pseudoClass)
-{
-  NS_NOTREACHED("Why did this get called?");
-  return PR_FALSE;
-}
-
-typedef PRBool
-  (NS_FASTCALL * PseudoClassMatcher)(RuleProcessorData&, PRBool setNodeFlags,
-                                     nsPseudoClassList* pseudoClass);
-// Only one of mFunc or mBit will be set; the other will be null or 0
-// respectively.  We could use a union, but then we'd still need to
-// differentiate somehow, eiher with another member in the struct or
-// with a boolean coming from _sowewhere_.
-struct PseudoClassInfo {
-  PseudoClassMatcher mFunc;
-  PRInt32 mBit;
-};
-
-static const PseudoClassInfo sPseudoClassInfo[] = {
-#define CSS_PSEUDO_CLASS(_name, _value)         \
-  { &_name##Matches, 0 },
-#define CSS_STATE_PSEUDO_CLASS(_name, _value, _bit) \
-  { nsnull, _bit },
-#include "nsCSSPseudoClassList.h"
-#undef CSS_STATE_PSEUDO_CLASS
-#undef CSS_PSEUDO_CLASS
-  // Add more entries for our fake values to make sure we can't
-  // index out of bounds into this array no matter what.
-  { nsnull, 0 },
-  { nsnull, 0 }
-};
-PR_STATIC_ASSERT(NS_ARRAY_LENGTH(sPseudoClassInfo) >
-                   nsCSSPseudoClasses::ePseudoClass_NotPseudoClass);
-
 // NOTE: For |aStateMask| to work correctly, it's important that any change
 // that changes multiple state bits include all those state bits in the
 // notification.  Otherwise, if multiple states change but we do separate
 // notifications then we might determine the style is not state-dependent when
 // it really is (e.g., determining that a :hover:active rule no longer matches
 // when both states are unset).
 
 // If |aForStyling| is false, we shouldn't mark slow-selector bits on nodes.
@@ -1776,18 +1283,16 @@ PR_STATIC_ASSERT(NS_ARRAY_LENGTH(sPseudo
 //    because of aStateMask
 static PRBool SelectorMatches(RuleProcessorData &data,
                               nsCSSSelector* aSelector,
                               PRInt32 aStateMask, // states NOT to test
                               PRBool aForStyling,
                               PRBool* const aDependence = nsnull) 
 
 {
-  NS_PRECONDITION(!aSelector->IsPseudoElement(),
-                  "Pseudo-element snuck into SelectorMatches?");
   // namespace/tag match
   // optimization : bail out early if we can
   if ((kNameSpaceID_Unknown != aSelector->mNameSpace &&
        data.mNameSpaceID != aSelector->mNameSpace))
     return PR_FALSE;
 
   if (aSelector->mLowercaseTag && 
       (data.mIsHTML ? aSelector->mLowercaseTag : aSelector->mCasedTag) !=
@@ -1846,92 +1351,473 @@ static PRBool SelectorMatches(RuleProces
                                     isCaseSensitive ?
                                       eCaseMatters : eIgnoreCase)) {
         return PR_FALSE;
       }
       classList = classList->mNext;
     }
   }
 
+  PRBool result = PR_TRUE;
   const PRBool isNegated = (aDependence != nsnull);
   // The selectors for which we set node bits are, unfortunately, early
   // in this function (because they're pseudo-classes, which are
   // generally quick to test, and thus earlier).  If they were later,
   // we'd probably avoid setting those bits in more cases where setting
   // them is unnecessary.
   NS_ASSERTION(aStateMask == 0 || !aForStyling,
                "aForStyling must be false if we're just testing for "
                "state-dependence");
   const PRBool setNodeFlags = aForStyling;
 
   // test for pseudo class match
+  // first-child, root, lang, active, focus, hover, link, visited...
+  // XXX disabled, enabled, selected, selection
   for (nsPseudoClassList* pseudoClass = aSelector->mPseudoClassList;
-       pseudoClass; pseudoClass = pseudoClass->mNext) {
-    // XXXbz special-case for :link and :visited, which are neither
-    // fish nor fowl
-    if (pseudoClass->mAtom == nsCSSPseudoClasses::link ||
-        pseudoClass->mAtom == nsCSSPseudoClasses::visited) {
-      if (!data.IsLink()) {
-        return PR_FALSE;
+       pseudoClass && result; pseudoClass = pseudoClass->mNext) {
+    PRInt32 stateToCheck = 0;
+    if (nsCSSPseudoClasses::firstNode == pseudoClass->mAtom) {
+      nsIContent *firstNode = nsnull;
+      nsIContent *parent = data.mParentContent;
+      if (parent) {
+        if (setNodeFlags)
+          parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
+
+        PRInt32 index = -1;
+        do {
+          firstNode = parent->GetChildAt(++index);
+          // stop at first non-comment and non-whitespace node
+        } while (firstNode &&
+                 !IsSignificantChild(firstNode, PR_TRUE, PR_FALSE));
+      }
+      result = (data.mContent == firstNode);
+    }
+    else if (nsCSSPseudoClasses::lastNode == pseudoClass->mAtom) {
+      nsIContent *lastNode = nsnull;
+      nsIContent *parent = data.mParentContent;
+      if (parent) {
+        if (setNodeFlags)
+          parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
+
+        PRUint32 index = parent->GetChildCount();
+        do {
+          lastNode = parent->GetChildAt(--index);
+          // stop at first non-comment and non-whitespace node
+        } while (lastNode &&
+                 !IsSignificantChild(lastNode, PR_TRUE, PR_FALSE));
+      }
+      result = (data.mContent == lastNode);
+    }
+    else if (nsCSSPseudoClasses::firstChild == pseudoClass->mAtom ||
+             nsCSSPseudoClasses::lastChild == pseudoClass->mAtom ||
+             nsCSSPseudoClasses::onlyChild == pseudoClass->mAtom) {
+      nsIContent *parent = data.mParentContent;
+      if (parent) {
+        const PRBool checkFirst =
+          pseudoClass->mAtom != nsCSSPseudoClasses::lastChild;
+        const PRBool checkLast =
+          pseudoClass->mAtom != nsCSSPseudoClasses::firstChild;
+        if (setNodeFlags)
+          parent->SetFlags(NODE_HAS_EDGE_CHILD_SELECTOR);
+
+        result = (!checkFirst ||
+                  data.GetNthIndex(PR_FALSE, PR_FALSE, PR_TRUE) == 1) &&
+                 (!checkLast ||
+                  data.GetNthIndex(PR_FALSE, PR_TRUE, PR_TRUE) == 1);
+      } else {
+        result = PR_FALSE;
       }
+    }
+    else if (nsCSSPseudoClasses::nthChild == pseudoClass->mAtom ||
+             nsCSSPseudoClasses::nthLastChild == pseudoClass->mAtom ||
+             nsCSSPseudoClasses::nthOfType == pseudoClass->mAtom ||
+             nsCSSPseudoClasses::nthLastOfType == pseudoClass->mAtom) {
+      nsIContent *parent = data.mParentContent;
+      if (parent) {
+        PRBool isOfType =
+          nsCSSPseudoClasses::nthOfType == pseudoClass->mAtom ||
+          nsCSSPseudoClasses::nthLastOfType == pseudoClass->mAtom;
+        PRBool isFromEnd =
+          nsCSSPseudoClasses::nthLastChild == pseudoClass->mAtom ||
+          nsCSSPseudoClasses::nthLastOfType == pseudoClass->mAtom;
+        if (setNodeFlags) {
+          if (isFromEnd)
+            parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
+          else
+            parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
+        }
+
+        const PRInt32 index = data.GetNthIndex(isOfType, isFromEnd, PR_FALSE);
+        if (index <= 0) {
+          // Node is anonymous content (not really a child of its parent).
+          result = PR_FALSE;
+        } else {
+          const PRInt32 a = pseudoClass->u.mNumbers[0];
+          const PRInt32 b = pseudoClass->u.mNumbers[1];
+          // result should be true if there exists n >= 0 such that
+          // a * n + b == index.
+          if (a == 0) {
+            result = b == index;
+          } else {
+            // Integer division in C does truncation (towards 0).  So
+            // check that the result is nonnegative, and that there was no
+            // truncation.
+            const PRInt32 n = (index - b) / a;
+            result = n >= 0 && (a * n == index - b);
+          }
+        }
+      } else {
+        result = PR_FALSE;
+      }
+    }
+    else if (nsCSSPseudoClasses::firstOfType == pseudoClass->mAtom ||
+             nsCSSPseudoClasses::lastOfType == pseudoClass->mAtom ||
+             nsCSSPseudoClasses::onlyOfType == pseudoClass->mAtom) {
+      nsIContent *parent = data.mParentContent;
+      if (parent) {
+        const PRBool checkFirst =
+          pseudoClass->mAtom != nsCSSPseudoClasses::lastOfType;
+        const PRBool checkLast =
+          pseudoClass->mAtom != nsCSSPseudoClasses::firstOfType;
+        if (setNodeFlags) {
+          if (checkLast)
+            parent->SetFlags(NODE_HAS_SLOW_SELECTOR);
+          else
+            parent->SetFlags(NODE_HAS_SLOW_SELECTOR_NOAPPEND);
+        }
+
+        result = (!checkFirst ||
+                  data.GetNthIndex(PR_TRUE, PR_FALSE, PR_TRUE) == 1) &&
+                 (!checkLast ||
+                  data.GetNthIndex(PR_TRUE, PR_TRUE, PR_TRUE) == 1);
+      } else {
+        result = PR_FALSE;
+      }
+    }
+    else if (nsCSSPseudoClasses::empty == pseudoClass->mAtom ||
+             nsCSSPseudoClasses::mozOnlyWhitespace == pseudoClass->mAtom) {
+      nsIContent *child = nsnull;
+      nsIContent *element = data.mContent;
+      const PRBool isWhitespaceSignificant =
+        nsCSSPseudoClasses::empty == pseudoClass->mAtom;
+      PRInt32 index = -1;
+
+      if (setNodeFlags)
+        element->SetFlags(NODE_HAS_EMPTY_SELECTOR);
+
+      do {
+        child = element->GetChildAt(++index);
+        // stop at first non-comment (and non-whitespace for
+        // :-moz-only-whitespace) node        
+      } while (child && !IsSignificantChild(child, PR_TRUE, isWhitespaceSignificant));
+      result = (child == nsnull);
+    }
+    else if (nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname == pseudoClass->mAtom) {
+      NS_ASSERTION(pseudoClass->u.mString, "Must have string!");
+      nsIContent *child = nsnull;
+      nsIContent *element = data.mContent;
+      PRInt32 index = -1;
+
+      if (setNodeFlags)
+        element->SetFlags(NODE_HAS_SLOW_SELECTOR);
+
+      do {
+        child = element->GetChildAt(++index);
+      } while (child &&
+               (!IsSignificantChild(child, PR_TRUE, PR_FALSE) ||
+                (child->GetNameSpaceID() == element->GetNameSpaceID() &&
+                 child->Tag()->Equals(nsDependentString(pseudoClass->u.mString)))));
+      result = (child == nsnull);
+    }
+    else if (nsCSSPseudoClasses::mozSystemMetric == pseudoClass->mAtom) {
+      NS_ASSERTION(pseudoClass->u.mString, "Must have string!");
+      nsCOMPtr<nsIAtom> metric = do_GetAtom(pseudoClass->u.mString);
+      result = nsCSSRuleProcessor::HasSystemMetric(metric);
+    }
+    else if (nsCSSPseudoClasses::mozHasHandlerRef == pseudoClass->mAtom) {
+      nsIContent *child = nsnull;
+      nsIContent *element = data.mContent;
+      PRInt32 index = -1;
 
-      if (aStateMask & NS_EVENT_STATE_VISITED) {
-        if (aDependence)
-          *aDependence = PR_TRUE;
-      } else if ((eLinkState_Visited == data.LinkState()) ==
-                 (nsCSSPseudoClasses::link == pseudoClass->mAtom)) {
-        // Visited but :link or unvisited but :visited
-        return PR_FALSE;
+      result = PR_FALSE;
+      if (element) {
+        do {
+          child = element->GetChildAt(++index);
+          if (child && child->IsHTML() &&
+              child->Tag() == nsGkAtoms::param &&
+              child->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
+                                 NS_LITERAL_STRING("pluginurl"), eIgnoreCase)) {
+            result = PR_TRUE;
+            break;
+          }
+        } while (child);
+      }
+    }
+    else if (nsCSSPseudoClasses::root == pseudoClass->mAtom) {
+      result = (data.mParentContent == nsnull &&
+                data.mContent &&
+                data.mContent ==
+                  data.mContent->GetOwnerDoc()->GetRootContent());
+    }
+    else if (nsCSSPseudoClasses::mozBoundElement == pseudoClass->mAtom) {
+      // XXXldb How do we know where the selector came from?  And what
+      // if there are multiple bindings, and we should be matching the
+      // outer one?
+      result = (data.mScopedRoot && data.mScopedRoot == data.mContent);
+    }
+    else if (nsCSSPseudoClasses::lang == pseudoClass->mAtom) {
+      NS_ASSERTION(nsnull != pseudoClass->u.mString, "null lang parameter");
+      result = PR_FALSE;
+      if (pseudoClass->u.mString && *pseudoClass->u.mString) {
+        // We have to determine the language of the current element.  Since
+        // this is currently no property and since the language is inherited
+        // from the parent we have to be prepared to look at all parent
+        // nodes.  The language itself is encoded in the LANG attribute.
+        const nsString* lang = data.GetLang();
+        if (lang && !lang->IsEmpty()) { // null check for out-of-memory
+          result = nsStyleUtil::DashMatchCompare(*lang,
+                                    nsDependentString(pseudoClass->u.mString), 
+                                    nsCaseInsensitiveStringComparator());
+        }
+        else if (data.mContent) {
+          nsIDocument* doc = data.mContent->GetDocument();
+          if (doc) {
+            // Try to get the language from the HTTP header or if this
+            // is missing as well from the preferences.
+            // The content language can be a comma-separated list of
+            // language codes.
+            nsAutoString language;
+            doc->GetContentLanguage(language);
+
+            nsDependentString langString(pseudoClass->u.mString);
+            language.StripWhitespace();
+            PRInt32 begin = 0;
+            PRInt32 len = language.Length();
+            while (begin < len) {
+              PRInt32 end = language.FindChar(PRUnichar(','), begin);
+              if (end == kNotFound) {
+                end = len;
+              }
+              if (nsStyleUtil::DashMatchCompare(Substring(language, begin, end-begin),
+                                   langString,
+                                   nsCaseInsensitiveStringComparator())) {
+                result = PR_TRUE;
+                break;
+              }
+              begin = end + 1;
+            }
+          }
+        }
+      }
+    } else if (nsCSSPseudoClasses::active == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_ACTIVE;
+    }
+    else if (nsCSSPseudoClasses::focus == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_FOCUS;
+    }
+    else if (nsCSSPseudoClasses::hover == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_HOVER;
+    }
+    else if (nsCSSPseudoClasses::mozDragOver == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_DRAGOVER;
+    }
+    else if (nsCSSPseudoClasses::target == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_URLTARGET;
+    }
+    else if (IsLinkPseudo(pseudoClass->mAtom)) {
+      if (data.IsLink()) {
+        if (nsCSSPseudoClasses::mozAnyLink == pseudoClass->mAtom) {
+          result = PR_TRUE;
+        }
+        else {
+          NS_ASSERTION(nsCSSPseudoClasses::link == pseudoClass->mAtom ||
+                       nsCSSPseudoClasses::visited == pseudoClass->mAtom,
+                       "somebody changed IsLinkPseudo");
+          NS_ASSERTION(data.LinkState() == eLinkState_Unvisited ||
+                       data.LinkState() == eLinkState_Visited,
+                       "unexpected link state for IsLink()");
+          if (aStateMask & NS_EVENT_STATE_VISITED) {
+            result = PR_TRUE;
+            if (aDependence)
+              *aDependence = PR_TRUE;
+          } else {
+            result = ((eLinkState_Unvisited == data.LinkState()) ==
+                      (nsCSSPseudoClasses::link == pseudoClass->mAtom));
+          }
+        }
+      }
+      else {
+        result = PR_FALSE;  // not a link
       }
-      continue;
+    }
+    else if (nsCSSPseudoClasses::checked == pseudoClass->mAtom) {
+      // This pseudoclass matches the selected state on the following elements:
+      //  <option>
+      //  <input type=checkbox>
+      //  <input type=radio>
+      stateToCheck = NS_EVENT_STATE_CHECKED;
+    }
+    else if (nsCSSPseudoClasses::enabled == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_ENABLED;
+    }
+    else if (nsCSSPseudoClasses::disabled == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_DISABLED;
+    }    
+    else if (nsCSSPseudoClasses::mozBroken == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_BROKEN;
+    }
+    else if (nsCSSPseudoClasses::mozUserDisabled == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_USERDISABLED;
+    }
+    else if (nsCSSPseudoClasses::mozSuppressed == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_SUPPRESSED;
+    }
+    else if (nsCSSPseudoClasses::mozLoading == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_LOADING;
+    }
+    else if (nsCSSPseudoClasses::mozTypeUnsupported == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_TYPE_UNSUPPORTED;
+    }
+    else if (nsCSSPseudoClasses::mozHandlerDisabled == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_HANDLER_DISABLED;
+    }
+    else if (nsCSSPseudoClasses::mozHandlerBlocked == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_HANDLER_BLOCKED;
+    }
+    else if (nsCSSPseudoClasses::defaultPseudo == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_DEFAULT;
+    }
+    else if (nsCSSPseudoClasses::required == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_REQUIRED;
+    }
+    else if (nsCSSPseudoClasses::optional == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_OPTIONAL;
+    }
+    else if (nsCSSPseudoClasses::valid == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_VALID;
+    }
+    else if (nsCSSPseudoClasses::invalid == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_INVALID;
+    }
+    else if (nsCSSPseudoClasses::inRange == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_INRANGE;
+    }
+    else if (nsCSSPseudoClasses::outOfRange == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_OUTOFRANGE;
+    }
+    else if (nsCSSPseudoClasses::mozReadOnly == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_MOZ_READONLY;
+    }
+    else if (nsCSSPseudoClasses::mozReadWrite == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_MOZ_READWRITE;
+    }
+    else if (nsCSSPseudoClasses::indeterminate == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_INDETERMINATE;
     }
-    const PseudoClassInfo& info = sPseudoClassInfo[pseudoClass->mType];
-    if (info.mFunc) {
-      if (!(*info.mFunc)(data, setNodeFlags, pseudoClass)) {
-        return PR_FALSE;
+    else if (nsCSSPseudoClasses::mozIsHTML == pseudoClass->mAtom) {
+      result = data.mIsHTML;
+    }
+    else if (nsCSSPseudoClasses::mozLocaleDir == pseudoClass->mAtom) {
+      nsIDocument* doc = data.mContent ? data.mContent->GetDocument() :
+                                         data.mPresContext->Document();
+
+      if (doc) {
+        PRBool docIsRTL = doc && doc->IsDocumentRightToLeft();
+
+        nsDependentString dirString(pseudoClass->u.mString);
+        NS_ASSERTION(dirString.EqualsLiteral("ltr") || dirString.EqualsLiteral("rtl"),
+                     "invalid value for -moz-locale-dir");
+
+        if (dirString.EqualsLiteral("rtl")) {
+          result = docIsRTL;
+        } else if (dirString.EqualsLiteral("ltr")) {
+          result = !docIsRTL;
+        }
+      }
+      else {
+        result = PR_FALSE;
+      }
+    }
+    else if (nsCSSPseudoClasses::mozLWTheme == pseudoClass->mAtom) {
+      nsIDocument* doc = data.mContent ? data.mContent->GetOwnerDoc() : nsnull;
+
+      if (doc) {
+        result = doc->GetDocumentLWTheme() > nsIDocument::Doc_Theme_None;
+      }
+      else {
+        result = PR_FALSE;
       }
-    } else {
-      PRInt32 stateToCheck = info.mBit;
-      NS_ABORT_IF_FALSE(stateToCheck != 0, "How did that happen?");
+    }
+    else if (nsCSSPseudoClasses::mozLWThemeBrightText == pseudoClass->mAtom) {
+      nsIDocument* doc = data.mContent ? data.mContent->GetOwnerDoc() : nsnull;
+
+      if (doc) {
+        result = doc->GetDocumentLWTheme() == nsIDocument::Doc_Theme_Bright;
+      }
+      else {
+        result = PR_FALSE;
+      }
+    }
+    else if (nsCSSPseudoClasses::mozLWThemeDarkText == pseudoClass->mAtom) {
+      nsIDocument* doc = data.mContent ? data.mContent->GetOwnerDoc() : nsnull;
+
+      if (doc) {
+        result = doc->GetDocumentLWTheme() == nsIDocument::Doc_Theme_Dark;
+      }
+      else {
+        result = PR_FALSE;
+      }
+    }
+#ifdef MOZ_MATHML
+    else if (nsCSSPseudoClasses::mozMathIncrementScriptLevel == pseudoClass->mAtom) {
+      stateToCheck = NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL;
+    }
+#endif
+    else {
+      NS_ERROR("CSS parser parsed a pseudo-class that we do not handle");
+      result = PR_FALSE;  // unknown pseudo class
+    }
+    if (stateToCheck) {
+      // check if the element is event-sensitive for :hover and :active
       if ((stateToCheck & (NS_EVENT_STATE_HOVER | NS_EVENT_STATE_ACTIVE)) &&
           data.mCompatMode == eCompatibility_NavQuirks &&
           // global selector (but don't check .class):
           !aSelector->HasTagSelector() && !aSelector->mIDList && 
           !aSelector->mAttrList &&
           // This (or the other way around) both make :not() asymmetric
           // in quirks mode (and it's hard to work around since we're
           // testing the current mNegations, not the first
           // (unnegated)). This at least makes it closer to the spec.
           !isNegated &&
           // important for |IsQuirkEventSensitive|:
           data.mIsHTMLContent && !data.IsLink() &&
           !IsQuirkEventSensitive(data.mContentTag)) {
         // In quirks mode, only make certain elements sensitive to
         // selectors ":hover" and ":active".
-        return PR_FALSE;
+        result = PR_FALSE;
       } else {
         if (aStateMask & stateToCheck) {
+          result = PR_TRUE;
           if (aDependence)
             *aDependence = PR_TRUE;
         } else {
-          if (!(data.ContentState() & stateToCheck)) {
-            return PR_FALSE;
-          }
+          result = (0 != (data.ContentState() & stateToCheck));
         }
       }
     }
   }
 
-  PRBool result = PR_TRUE;
-  if (aSelector->mAttrList) {
+  if (result && aSelector->mAttrList) {
     // test for attribute match
     if (!data.mHasAttributes) {
       // if no attributes on the content, no match
       return PR_FALSE;
     } else {
+      NS_ASSERTION(data.mContent,
+                   "Must have content if data.mHasAttributes is true!");
       result = PR_TRUE;
       nsAttrSelector* attr = aSelector->mAttrList;
       nsIAtom* matchAttribute;
 
       do {
         matchAttribute = data.mIsHTML ? attr->mLowercaseAttr : attr->mCasedAttr;
         if (attr->mNameSpace == kNameSpaceID_Unknown) {
           // Attr selector with a wildcard namespace.  We have to examine all
@@ -2116,17 +2002,17 @@ static PRBool SelectorMatchesTree(RulePr
     prevdata = data;
   }
   return PR_TRUE; // all the selectors matched.
 }
 
 static void ContentEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
                             void* aData)
 {
-  RuleProcessorData* data = (RuleProcessorData*)aData;
+  ElementRuleProcessorData* data = (ElementRuleProcessorData*)aData;
 
   if (SelectorMatches(*data, aSelector, 0, PR_TRUE)) {
     nsCSSSelector *next = aSelector->mNext;
     if (!next || SelectorMatchesTree(*data, next, PR_TRUE)) {
       // for performance, require that every implementation of
       // nsICSSStyleRule return the same pointer for nsIStyleRule (why
       // would anything multiply inherit nsIStyleRule anyway?)
 #ifdef DEBUG
@@ -2154,93 +2040,80 @@ nsCSSRuleProcessor::RulesMatching(Elemen
                                          aData->mContentID,
                                          aData->mClasses,
                                          ContentEnumFunc,
                                          aData);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsCSSRuleProcessor::RulesMatching(PseudoElementRuleProcessorData* aData)
+static void PseudoEnumFunc(nsICSSStyleRule* aRule, nsCSSSelector* aSelector,
+                           void* aData)
 {
-  NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT),
-                  "content must be element");
+  PseudoRuleProcessorData* data = (PseudoRuleProcessorData*)aData;
+
+  if (!aSelector->IsPseudoElement())
+    return;
+
+  NS_ASSERTION(aSelector->mLowercaseTag == data->mPseudoTag, "RuleHash failure");
+  PRBool matches = PR_TRUE;
+  if (data->mComparator)
+    data->mComparator->PseudoMatches(data->mPseudoTag, aSelector, &matches);
+
+  if (matches) {
+    nsCSSSelector *selector = aSelector->mNext;
+
+    if (selector) { // test next selector specially
+      if (PRUnichar('+') == selector->mOperator) {
+        return; // not valid here, can't match
+      }
+      if (SelectorMatches(*data, selector, 0, PR_TRUE)) {
+        selector = selector->mNext;
+      }
+      else {
+        if (PRUnichar('>') == selector->mOperator) {
+          return; // immediate parent didn't match
+        }
+      }
+    }
+
+    if (selector && 
+        (! SelectorMatchesTree(*data, selector, PR_TRUE))) {
+      return; // remaining selectors didn't match
+    }
+
+    // for performance, require that every implementation of
+    // nsICSSStyleRule return the same pointer for nsIStyleRule (why
+    // would anything multiply inherit nsIStyleRule anyway?)
+#ifdef DEBUG
+    nsCOMPtr<nsIStyleRule> iRule = do_QueryInterface(aRule);
+    NS_ASSERTION(static_cast<nsIStyleRule*>(aRule) == iRule.get(),
+                 "Please fix QI so this performance optimization is valid");
+#endif
+    data->mRuleWalker->Forward(static_cast<nsIStyleRule*>(aRule));
+    // nsStyleSet will deal with the !important rule
+  }
+}
+
+NS_IMETHODIMP
+nsCSSRuleProcessor::RulesMatching(PseudoRuleProcessorData* aData)
+{
+  NS_PRECONDITION(!aData->mContent ||
+                  aData->mContent->IsNodeOfType(nsINode::eELEMENT),
+                  "content (if present) must be element");
 
   RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
 
   if (cascade) {
-    RuleHash* ruleHash = cascade->mPseudoElementRuleHashes[aData->mPseudoType];
-    if (ruleHash) {
-      ruleHash->EnumerateAllRules(aData->mNameSpaceID,
-                                  aData->mContentTag,
-                                  aData->mContentID,
-                                  aData->mClasses,
-                                  ContentEnumFunc,
-                                  aData);
-    }
+    cascade->mRuleHash.EnumerateTagRules(aData->mPseudoTag,
+                                         PseudoEnumFunc, aData);
   }
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsCSSRuleProcessor::RulesMatching(AnonBoxRuleProcessorData* aData)
-{
-  RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
-
-  if (cascade && cascade->mAnonBoxRules.entryCount) {
-    RuleHashTagTableEntry* entry = static_cast<RuleHashTagTableEntry*>
-      (PL_DHashTableOperate(&cascade->mAnonBoxRules, aData->mPseudoTag,
-                            PL_DHASH_LOOKUP));
-    if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
-      for (RuleValue *value = entry->mRules; value; value = value->mNext) {
-        // for performance, require that every implementation of
-        // nsICSSStyleRule return the same pointer for nsIStyleRule (why
-        // would anything multiply inherit nsIStyleRule anyway?)
-#ifdef DEBUG
-        nsCOMPtr<nsIStyleRule> iRule = do_QueryInterface(value->mRule);
-        NS_ASSERTION(static_cast<nsIStyleRule*>(value->mRule) == iRule.get(),
-                     "Please fix QI so this performance optimization is valid");
-#endif
-        aData->mRuleWalker->Forward(static_cast<nsIStyleRule*>(value->mRule));
-      }
-    }
-  }
-  return NS_OK;
-}
-
-#ifdef MOZ_XUL
-NS_IMETHODIMP
-nsCSSRuleProcessor::RulesMatching(XULTreeRuleProcessorData* aData)
-{
-  NS_PRECONDITION(aData->mContent->IsNodeOfType(nsINode::eELEMENT),
-                  "content must be element");
-
-  RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
-
-  if (cascade && cascade->mXULTreeRules.entryCount) {
-    RuleHashTagTableEntry* entry = static_cast<RuleHashTagTableEntry*>
-      (PL_DHashTableOperate(&cascade->mXULTreeRules, aData->mPseudoTag,
-                            PL_DHASH_LOOKUP));
-    if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
-      for (RuleValue *value = entry->mRules; value; value = value->mNext) {
-        PRBool matches = PR_TRUE;
-        aData->mComparator->PseudoMatches(aData->mPseudoTag, value->mSelector,
-                                          &matches);
-        if (matches) {
-          ContentEnumFunc(value->mRule, value->mSelector->mNext,
-                          static_cast<RuleProcessorData*>(aData));
-        }
-      }
-    }
-  }
-  return NS_OK;
-}
-#endif
-
 inline PRBool
 IsSiblingOperator(PRUnichar oper)
 {
   return oper == PRUnichar('+') || oper == PRUnichar('~');
 }
 
 NS_IMETHODIMP
 nsCSSRuleProcessor::HasStateDependentStyle(StateRuleProcessorData* aData,
@@ -2451,99 +2324,63 @@ nsCSSRuleProcessor::ClearRuleCascades()
 
 // This function should return true only for selectors that need to be
 // checked by |HasStateDependentStyle|.
 inline
 PRBool IsStateSelector(nsCSSSelector& aSelector)
 {
   for (nsPseudoClassList* pseudoClass = aSelector.mPseudoClassList;
        pseudoClass; pseudoClass = pseudoClass->mNext) {
-    // Tree pseudo-elements overload mPseudoClassList for things that
-    // aren't pseudo-classes.
-    if (pseudoClass->mType >= nsCSSPseudoClasses::ePseudoClass_Count) {
-      continue;
-    }
-    // XXXbz special-case for now for :link/:visited, since they're
-    // sorta-states-but-not-really right now.
-    if (sPseudoClassInfo[pseudoClass->mType].mBit ||
-        pseudoClass->mAtom == nsCSSPseudoClasses::link ||
-        pseudoClass->mAtom == nsCSSPseudoClasses::visited) {
+    if ((pseudoClass->mAtom == nsCSSPseudoClasses::active) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::checked) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::mozDragOver) || 
+        (pseudoClass->mAtom == nsCSSPseudoClasses::focus) || 
+        (pseudoClass->mAtom == nsCSSPseudoClasses::hover) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::target) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::link) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::visited) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::enabled) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::disabled) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::mozBroken) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::mozUserDisabled) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::mozSuppressed) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::mozLoading) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::required) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::optional) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::valid) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::invalid) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::inRange) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::outOfRange) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::mozReadOnly) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::mozReadWrite) ||
+        (pseudoClass->mAtom == nsCSSPseudoClasses::indeterminate) ||
+#ifdef MOZ_MATHML
+        (pseudoClass->mAtom == nsCSSPseudoClasses::mozMathIncrementScriptLevel) ||
+#endif
+        (pseudoClass->mAtom == nsCSSPseudoClasses::defaultPseudo)) {
       return PR_TRUE;
     }
   }
   return PR_FALSE;
 }
 
 static PRBool
-AddRule(RuleValue* aRuleInfo, RuleCascadeData* aCascade)
+AddRule(RuleValue* aRuleInfo, void* aCascade)
 {
-  RuleCascadeData * const cascade = aCascade;
+  RuleCascadeData *cascade = static_cast<RuleCascadeData*>(aCascade);
 
   // Build the rule hash.
-  nsCSSPseudoElements::Type pseudoType = aRuleInfo->mSelector->PseudoType();
-  if (NS_LIKELY(pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement)) {
-    cascade->mRuleHash.PrependRule(aRuleInfo);
-  } else if (pseudoType < nsCSSPseudoElements::ePseudo_PseudoElementCount) {
-    RuleHash*& ruleHash = cascade->mPseudoElementRuleHashes[pseudoType];
-    if (!ruleHash) {
-      ruleHash = new RuleHash(cascade->mQuirksMode);
-      if (!ruleHash) {
-        // Out of memory; give up
-        return PR_FALSE;
-      }
-    }
-    NS_ASSERTION(aRuleInfo->mSelector->mNext,
-                 "Must have mNext; parser screwed up");
-    NS_ASSERTION(aRuleInfo->mSelector->mNext->mOperator == '>',
-                 "Unexpected mNext combinator");
-    aRuleInfo->mSelector = aRuleInfo->mSelector->mNext;
-    ruleHash->PrependRule(aRuleInfo);
-  } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
-    NS_ASSERTION(!aRuleInfo->mSelector->mCasedTag &&
-                 !aRuleInfo->mSelector->mIDList &&
-                 !aRuleInfo->mSelector->mClassList &&
-                 !aRuleInfo->mSelector->mPseudoClassList &&
-                 !aRuleInfo->mSelector->mAttrList &&
-                 !aRuleInfo->mSelector->mNegations &&
-                 !aRuleInfo->mSelector->mNext &&
-                 aRuleInfo->mSelector->mNameSpace == kNameSpaceID_Unknown,
-                 "Parser messed up with anon box selector");
-
-    // Index doesn't matter here, since we'll just be walking these
-    // rules in order; just pass 0.
-    DoPrependRuleToTagTable(&cascade->mAnonBoxRules,
-                            aRuleInfo->mSelector->mLowercaseTag,
-                            aRuleInfo, 0);
-  } else {
-#ifdef MOZ_XUL
-    NS_ASSERTION(pseudoType == nsCSSPseudoElements::ePseudo_XULTree,
-                 "Unexpected pseudo type");
-    // Index doesn't matter here, since we'll just be walking these
-    // rules in order; just pass 0.
-    DoPrependRuleToTagTable(&cascade->mXULTreeRules,
-                            aRuleInfo->mSelector->mLowercaseTag,
-                            aRuleInfo, 0);
-#else
-    NS_NOTREACHED("Unexpected pseudo type");
-#endif
-  }
+  cascade->mRuleHash.PrependRule(aRuleInfo);
 
   nsTArray<nsCSSSelector*>* stateArray = &cascade->mStateSelectors;
   nsTArray<nsCSSSelector*>* classArray = &cascade->mClassSelectors;
   nsTArray<nsCSSSelector*>* idArray = &cascade->mIDSelectors;
   
   for (nsCSSSelector* selector = aRuleInfo->mSelector;
            selector; selector = selector->mNext) {
-    if (selector->IsPseudoElement()) {
-      NS_ASSERTION(!selector->mNegations, "Shouldn't have negations");
-      // Make sure these selectors don't end up in the hashtables we use to
-      // match against actual elements, no matter what.  Normally they wouldn't
-      // anyway, but trees overload mPseudoClassList with weird stuff.
-      continue;
-    }
     // It's worth noting that this loop over negations isn't quite
     // optimal for two reasons.  One, we could add something to one of
     // these lists twice, which means we'll check it twice, but I don't
     // think that's worth worrying about.   (We do the same for multiple
     // attribute selectors on the same attribute.)  Two, we don't really
     // need to check negations past the first in the current
     // implementation (and they're rare as well), but that might change
     // in the future if :not() is extended. 
@@ -2849,17 +2686,16 @@ nsCSSRuleProcessor::RefreshRuleCascade(n
 
 /* static */ PRBool
 nsCSSRuleProcessor::SelectorListMatches(RuleProcessorData& aData,
                                         nsCSSSelectorList* aSelectorList)
 {
   while (aSelectorList) {
     nsCSSSelector* sel = aSelectorList->mSelectors;
     NS_ASSERTION(sel, "Should have *some* selectors");
-    NS_ASSERTION(!sel->IsPseudoElement(), "Shouldn't have been called");
     if (SelectorMatches(aData, sel, 0, PR_FALSE)) {
       nsCSSSelector* next = sel->mNext;
       if (!next || SelectorMatchesTree(aData, next, PR_FALSE)) {
         return PR_TRUE;
       }
     }
 
     aSelectorList = aSelectorList->mNext;
--- a/layout/style/nsCSSRuleProcessor.h
+++ b/layout/style/nsCSSRuleProcessor.h
@@ -78,33 +78,25 @@ public:
 
   static void Startup();
   static void FreeSystemMetrics();
   static PRBool HasSystemMetric(nsIAtom* aMetric);
 
   /*
    * Returns true if the given RuleProcessorData matches one of the
    * selectors in aSelectorList.  Note that this method will assume
-   * the matching is not for styling purposes.  aSelectorList must not
-   * include any pseudo-element selectors.  aSelectorList is allowed
-   * to be null; in this case PR_FALSE will be returned.
+   * the matching is not for styling purposes.
    */
   static PRBool SelectorListMatches(RuleProcessorData& aData,
                                     nsCSSSelectorList* aSelectorList);
 
   // nsIStyleRuleProcessor
   NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
 
-  NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
-
-  NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
-
-#ifdef MOZ_XUL
-  NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData);
-#endif
+  NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
 
   NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
                                     nsReStyleHint* aResult);
 
   virtual nsReStyleHint
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
 
   NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext,
--- a/layout/style/nsCSSStyleRule.cpp
+++ b/layout/style/nsCSSStyleRule.cpp
@@ -77,18 +77,16 @@
 #include "nsCSSPseudoClasses.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsTArray.h"
 
 #include "nsContentUtils.h"
 #include "nsContentErrors.h"
 #include "mozAutoDocUpdate.h"
 
-#include "prlog.h"
-
 #define NS_IF_CLONE(member_)                                                  \
   PR_BEGIN_MACRO                                                              \
     if (member_) {                                                            \
       result->member_ = member_->Clone();                                     \
       if (!result->member_) {                                                 \
         delete result;                                                        \
         return nsnull;                                                        \
       }                                                                       \
@@ -131,70 +129,62 @@ nsAtomList::Clone(PRBool aDeep) const
 }
 
 nsAtomList::~nsAtomList(void)
 {
   MOZ_COUNT_DTOR(nsAtomList);
   NS_CSS_DELETE_LIST_MEMBER(nsAtomList, this, mNext);
 }
 
-nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom,
-                                     nsCSSPseudoClasses::Type aType)
+nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom)
   : mAtom(aAtom),
-    mType(aType),
     mNext(nsnull)
 {
   NS_ASSERTION(!nsCSSPseudoClasses::HasStringArg(aAtom) &&
                !nsCSSPseudoClasses::HasNthPairArg(aAtom),
                "unexpected pseudo-class");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mMemory = nsnull;
 }
 
-nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom,
-                                     nsCSSPseudoClasses::Type aType,
-                                     const PRUnichar* aString)
+nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom, const PRUnichar* aString)
   : mAtom(aAtom),
-    mType(aType),
     mNext(nsnull)
 {
   NS_ASSERTION(nsCSSPseudoClasses::HasStringArg(aAtom),
                "unexpected pseudo-class");
   NS_ASSERTION(aString, "string expected");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mString = NS_strdup(aString);
 }
 
-nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom,
-                                     nsCSSPseudoClasses::Type aType,
-                                     const PRInt32* aIntPair)
+nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom, const PRInt32* aIntPair)
   : mAtom(aAtom),
-    mType(aType),
     mNext(nsnull)
 {
   NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(aAtom),
                "unexpected pseudo-class");
   NS_ASSERTION(aIntPair, "integer pair expected");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mNumbers =
     static_cast<PRInt32*>(nsMemory::Clone(aIntPair, sizeof(PRInt32) * 2));
 }
 
 nsPseudoClassList*
 nsPseudoClassList::Clone(PRBool aDeep) const
 {
   nsPseudoClassList *result;
   if (!u.mMemory) {
-    result = new nsPseudoClassList(mAtom, mType);
+    result = new nsPseudoClassList(mAtom);
   } else if (nsCSSPseudoClasses::HasStringArg(mAtom)) {
-    result = new nsPseudoClassList(mAtom, mType, u.mString);
+    result = new nsPseudoClassList(mAtom, u.mString);
   } else {
     NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(mAtom),
                  "unexpected pseudo-class");
-    result = new nsPseudoClassList(mAtom, mType, u.mNumbers);
+    result = new nsPseudoClassList(mAtom, u.mNumbers);
   }
 
   if (aDeep)
     NS_CSS_CLONE_LIST_MEMBER(nsPseudoClassList, this, mNext, result,
                              (PR_FALSE));
 
   return result;
 }
@@ -285,36 +275,32 @@ nsCSSSelector::nsCSSSelector(void)
     mCasedTag(nsnull),
     mIDList(nsnull),
     mClassList(nsnull),
     mPseudoClassList(nsnull),
     mAttrList(nsnull),
     mNegations(nsnull),
     mNext(nsnull),
     mNameSpace(kNameSpaceID_Unknown),
-    mOperator(0),
-    mPseudoType(nsCSSPseudoElements::ePseudo_NotPseudoElement)
+    mOperator(0)
 {
   MOZ_COUNT_CTOR(nsCSSSelector);
-  // Make sure mPseudoType can hold all nsCSSPseudoElements::Type values
-  PR_STATIC_ASSERT(nsCSSPseudoElements::ePseudo_MAX < PR_INT16_MAX);
 }
 
 nsCSSSelector*
 nsCSSSelector::Clone(PRBool aDeepNext, PRBool aDeepNegations) const
 {
   nsCSSSelector *result = new nsCSSSelector();
   if (!result)
     return nsnull;
 
   result->mNameSpace = mNameSpace;
   result->mLowercaseTag = mLowercaseTag;
   result->mCasedTag = mCasedTag;
   result->mOperator = mOperator;
-  result->mPseudoType = mPseudoType;
   
   NS_IF_CLONE(mIDList);
   NS_IF_CLONE(mClassList);
   NS_IF_CLONE(mPseudoClassList);
   NS_IF_CLONE(mAttrList);
 
   // No need to worry about multiple levels of recursion since an
   // mNegations can't have an mNext.
@@ -395,34 +381,31 @@ void nsCSSSelector::AddClass(const nsStr
     nsAtomList** list = &mClassList;
     while (nsnull != *list) {
       list = &((*list)->mNext);
     }
     *list = new nsAtomList(aClass);
   }
 }
 
-void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
-                                   nsCSSPseudoClasses::Type aType)
+void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass)
 {
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType));
+  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass));
 }
 
 void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
-                                   nsCSSPseudoClasses::Type aType,
                                    const PRUnichar* aString)
 {
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType, aString));
+  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aString));
 }
 
 void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
-                                   nsCSSPseudoClasses::Type aType,
                                    const PRInt32* aIntPair)
 {
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType, aIntPair));
+  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aIntPair));
 }
 
 void nsCSSSelector::AddPseudoClassInternal(nsPseudoClassList *aPseudoClass)
 {
   nsPseudoClassList** list = &mPseudoClassList;
   while (nsnull != *list) {
     list = &((*list)->mNext);
   }
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -320,26 +320,27 @@ nsComputedDOMStyle::GetPropertyValue(con
 /* static */
 already_AddRefed<nsStyleContext>
 nsComputedDOMStyle::GetStyleContextForContent(nsIContent* aContent,
                                               nsIAtom* aPseudo,
                                               nsIPresShell* aPresShell)
 {
   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eELEMENT),
                "aContent must be an element");
-
-  // If there's no pres shell, get it from the content
-  if (!aPresShell) {
-    aPresShell = GetPresShellForContent(aContent);
-    if (!aPresShell)
-      return nsnull;
+  if (!aPseudo) {
+    // If there's no pres shell, get it from the content
+    if (!aPresShell) {
+      aPresShell = GetPresShellForContent(aContent);
+      if (!aPresShell)
+        return nsnull;
+    }
+
+    aPresShell->FlushPendingNotifications(Flush_Style);
   }
 
-  aPresShell->FlushPendingNotifications(Flush_Style);
-
   return GetStyleContextForContentNoFlush(aContent, aPseudo, aPresShell);
 }
 
 /* static */
 already_AddRefed<nsStyleContext>
 nsComputedDOMStyle::GetStyleContextForContentNoFlush(nsIContent* aContent,
                                                      nsIAtom* aPseudo,
                                                      nsIPresShell* aPresShell)
@@ -370,30 +371,26 @@ nsComputedDOMStyle::GetStyleContextForCo
   }
 
   // No frame has been created or we have a pseudo, so resolve the
   // style ourselves
   nsRefPtr<nsStyleContext> parentContext;
   nsIContent* parent = aPseudo ? aContent : aContent->GetParent();
   // Don't resolve parent context for document fragments.
   if (parent && parent->IsNodeOfType(nsINode::eELEMENT))
-    parentContext = GetStyleContextForContentNoFlush(parent, nsnull, aPresShell);
+    parentContext = GetStyleContextForContent(parent, nsnull, aPresShell);
 
   nsPresContext *presContext = aPresShell->GetPresContext();
   if (!presContext)
     return nsnull;
 
   nsStyleSet *styleSet = aPresShell->StyleSet();
 
   if (aPseudo) {
-    nsCSSPseudoElements::Type type = nsCSSPseudoElements::GetPseudoType(aPseudo);
-    if (type >= nsCSSPseudoElements::ePseudo_PseudoElementCount) {
-      return nsnull;
-    }
-    return styleSet->ResolvePseudoElementStyle(aContent, type, parentContext);
+    return styleSet->ResolvePseudoStyleFor(aContent, aPseudo, parentContext);
   }
 
   return styleSet->ResolveStyleFor(aContent, parentContext);
 }
 
 /* static */
 nsIPresShell*
 nsComputedDOMStyle::GetPresShellForContent(nsIContent* aContent)
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -84,23 +84,17 @@ public:
   // style sheet owner info
   NS_IMETHOD GetParentSheet(nsIStyleSheet*& aParent) const;  // will be null
   NS_IMETHOD GetOwningDocument(nsIDocument*& aDocument) const;
   NS_IMETHOD SetOwningDocument(nsIDocument* aDocument);
 
   // nsIStyleRuleProcessor api
   NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
 
-  NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
-
-  NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
-
-#ifdef MOZ_XUL
-  NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData);
-#endif
+  NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
 
   NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
                                     nsReStyleHint* aResult);
 
   virtual nsReStyleHint
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
   NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext,
                                   PRBool* aResult);
@@ -140,52 +134,40 @@ NS_IMPL_ISUPPORTS3(HTMLCSSStyleSheetImpl
                    nsIHTMLCSSStyleSheet,
                    nsIStyleSheet,
                    nsIStyleRuleProcessor)
 
 NS_IMETHODIMP
 HTMLCSSStyleSheetImpl::RulesMatching(ElementRuleProcessorData* aData)
 {
   nsIContent* content = aData->mContent;
-
-  // just get the one and only style rule from the content's STYLE attribute
-  nsICSSStyleRule* rule = content->GetInlineStyleRule();
-  if (rule)
-    aData->mRuleWalker->Forward(rule);
+  
+  if (content) {
+    // just get the one and only style rule from the content's STYLE attribute
+    nsICSSStyleRule* rule = content->GetInlineStyleRule();
+    if (rule)
+      aData->mRuleWalker->Forward(rule);
 
 #ifdef MOZ_SMIL
-  rule = content->GetSMILOverrideStyleRule();
-  if (rule)
-    aData->mRuleWalker->Forward(rule);
+    rule = content->GetSMILOverrideStyleRule();
+    if (rule)
+      aData->mRuleWalker->Forward(rule);
 #endif // MOZ_SMIL
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-HTMLCSSStyleSheetImpl::RulesMatching(PseudoElementRuleProcessorData* aData)
+HTMLCSSStyleSheetImpl::RulesMatching(PseudoRuleProcessorData* aData)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-HTMLCSSStyleSheetImpl::RulesMatching(AnonBoxRuleProcessorData* aData)
-{
-  return NS_OK;
-}
-
-#ifdef MOZ_XUL
-NS_IMETHODIMP
-HTMLCSSStyleSheetImpl::RulesMatching(XULTreeRuleProcessorData* aData)
-{
-  return NS_OK;
-}
-#endif
-
-NS_IMETHODIMP
 HTMLCSSStyleSheetImpl::Init(nsIURI* aURL, nsIDocument* aDocument)
 {
   NS_PRECONDITION(aURL && aDocument, "null ptr");
   if (! aURL || ! aDocument)
     return NS_ERROR_NULL_POINTER;
 
   if (mURL || mDocument)
     return NS_ERROR_ALREADY_INITIALIZED;
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -558,41 +558,28 @@ nsHTMLStyleSheet::MediumFeaturesChanged(
                                         PRBool* aRulesChanged)
 {
   *aRulesChanged = PR_FALSE;
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
-nsHTMLStyleSheet::RulesMatching(PseudoElementRuleProcessorData* aData)
-{
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsHTMLStyleSheet::RulesMatching(AnonBoxRuleProcessorData* aData)
+nsHTMLStyleSheet::RulesMatching(PseudoRuleProcessorData* aData)
 {
   nsIAtom* pseudoTag = aData->mPseudoTag;
   if (pseudoTag == nsCSSAnonBoxes::tableCol) {
     nsRuleWalker *ruleWalker = aData->mRuleWalker;
     if (ruleWalker) {
       ruleWalker->Forward(mTableColRule);
     }
   }
   return NS_OK;
 }
 
-#ifdef MOZ_XUL
-NS_IMETHODIMP
-nsHTMLStyleSheet::RulesMatching(XULTreeRuleProcessorData* aData)
-{
-  return NS_OK;
-}
-#endif
 
   // nsIStyleSheet api
 NS_IMETHODIMP
 nsHTMLStyleSheet::GetSheetURI(nsIURI** aSheetURI) const
 {
   *aSheetURI = mURL;
   NS_IF_ADDREF(*aSheetURI);
   return NS_OK;
--- a/layout/style/nsHTMLStyleSheet.h
+++ b/layout/style/nsHTMLStyleSheet.h
@@ -74,21 +74,17 @@ public:
   NS_IMETHOD GetOwningDocument(nsIDocument*& aDocument) const;
   NS_IMETHOD SetOwningDocument(nsIDocument* aDocumemt);
 #ifdef DEBUG
   virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const;
 #endif
 
   // nsIStyleRuleProcessor API
   NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
-  NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
-  NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
-#ifdef MOZ_XUL
-  NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData);
-#endif
+  NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
   NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
                                     nsReStyleHint* aResult);
   virtual nsReStyleHint
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
   NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext,
                                    PRBool* aRulesChanged);
 
   nsresult Init(nsIURI* aURL, nsIDocument* aDocument);
--- a/layout/style/nsICSSStyleRule.h
+++ b/layout/style/nsICSSStyleRule.h
@@ -47,18 +47,16 @@
 
 //#include <stdio.h>
 #include "nsICSSRule.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsCSSProps.h"
 #include "nsCSSValue.h"
 #include "nsIAtom.h"
-#include "nsCSSPseudoElements.h"
-#include "nsCSSPseudoClasses.h"
 
 class nsIAtom;
 class nsCSSDeclaration;
 class nsICSSStyleSheet;
 
 struct nsAtomList {
 public:
   nsAtomList(nsIAtom* aAtom);
@@ -75,21 +73,19 @@ private:
 
   // These are not supported and are not implemented! 
   nsAtomList(const nsAtomList& aCopy);
   nsAtomList& operator=(const nsAtomList& aCopy); 
 };
 
 struct nsPseudoClassList {
 public:
-  nsPseudoClassList(nsIAtom* aAtom, nsCSSPseudoClasses::Type aType);
-  nsPseudoClassList(nsIAtom* aAtom, nsCSSPseudoClasses::Type aType,
-                    const PRUnichar *aString);
-  nsPseudoClassList(nsIAtom* aAtom, nsCSSPseudoClasses::Type aType,
-                    const PRInt32 *aIntPair);
+  nsPseudoClassList(nsIAtom* aAtom);
+  nsPseudoClassList(nsIAtom* aAtom, const PRUnichar *aString);
+  nsPseudoClassList(nsIAtom* aAtom, const PRInt32 *aIntPair);
   ~nsPseudoClassList(void);
 
   /** Do a deep clone.  Should be used only on the first in the linked list. */
   nsPseudoClassList* Clone() const { return Clone(PR_TRUE); }
 
   nsCOMPtr<nsIAtom> mAtom;
   union {
     // For a given value of mAtom, we have either:
@@ -98,17 +94,16 @@ public:
     //   b. a string value, which means mString/mMemory is non-null
     //      (if nsCSSPseudoClasses::HasStringArg(mAtom))
     //   c. an integer pair value, which means mNumbers/mMemory is non-null
     //      (if nsCSSPseudoClasses::HasNthPairArg(mAtom))
     void*           mMemory; // both pointer types use NS_Alloc/NS_Free
     PRUnichar*      mString;
     PRInt32*        mNumbers;
   } u;
-  nsCSSPseudoClasses::Type mType;
   nsPseudoClassList* mNext;
 private: 
   nsPseudoClassList* Clone(PRBool aDeep) const;
 
   // These are not supported and are not implemented! 
   nsPseudoClassList(const nsPseudoClassList& aCopy);
   nsPseudoClassList& operator=(const nsPseudoClassList& aCopy); 
 };
@@ -158,21 +153,19 @@ public:
   /** Do a deep clone.  Should be used only on the first in the linked list. */
   nsCSSSelector* Clone() const { return Clone(PR_TRUE, PR_TRUE); }
 
   void Reset(void);
   void SetNameSpace(PRInt32 aNameSpace);
   void SetTag(const nsString& aTag);
   void AddID(const nsString& aID);
   void AddClass(const nsString& aClass);
-  void AddPseudoClass(nsIAtom* aPseudoClass, nsCSSPseudoClasses::Type aType);
-  void AddPseudoClass(nsIAtom* aPseudoClass, nsCSSPseudoClasses::Type aType,
-                      const PRUnichar* aString);
-  void AddPseudoClass(nsIAtom* aPseudoClass, nsCSSPseudoClasses::Type aType,
-                      const PRInt32* aIntPair);
+  void AddPseudoClass(nsIAtom* aPseudoClass);
+  void AddPseudoClass(nsIAtom* aPseudoClass, const PRUnichar* aString);
+  void AddPseudoClass(nsIAtom* aPseudoClass, const PRInt32* aIntPair);
   void AddAttribute(PRInt32 aNameSpace, const nsString& aAttr);
   void AddAttribute(PRInt32 aNameSpace, const nsString& aAttr, PRUint8 aFunc, 
                     const nsString& aValue, PRBool aCaseSensitive);
   void SetOperator(PRUnichar aOperator);
 
   inline PRBool HasTagSelector() const {
     return !!mCasedTag;
   }
@@ -201,43 +194,32 @@ private:
   // happens if and only if the default namespace would apply to this
   // selector).
   PRBool CanBeNamespaced(PRBool aIsNegated) const;
   // Calculate the specificity of this selector (not including its mNext
   // or its mNegations).
   PRInt32 CalcWeightWithoutNegations() const;
 
 public:
-  // Get and set the selector's pseudo type
-  nsCSSPseudoElements::Type PseudoType() const {
-    return static_cast<nsCSSPseudoElements::Type>(mPseudoType);
-  }
-  void SetPseudoType(nsCSSPseudoElements::Type aType) {
-    NS_ASSERTION(aType > PR_INT16_MIN && aType < PR_INT16_MAX, "Out of bounds");
-    mPseudoType = static_cast<PRInt16>(aType);
-  }
-
   // For case-sensitive documents, mLowercaseTag is the same as mCasedTag,
   // but in case-insensitive documents (HTML) mLowercaseTag is lowercase.
   // Also, for pseudo-elements mCasedTag will be null but mLowercaseTag
   // contains their name.
   nsCOMPtr<nsIAtom> mLowercaseTag;
   nsCOMPtr<nsIAtom> mCasedTag;
   nsAtomList*     mIDList;
   nsAtomList*     mClassList;
   nsPseudoClassList* mPseudoClassList; // atom for the pseudo, string for
                                        // the argument to functional pseudos
   nsAttrSelector* mAttrList;
   nsCSSSelector*  mNegations;
   nsCSSSelector*  mNext;
   PRInt32         mNameSpace;
   PRUnichar       mOperator;
-private:
-  // PRInt16 to make sure it packs well with mOperator
-  PRInt16        mPseudoType;
+private: 
   // These are not supported and are not implemented! 
   nsCSSSelector(const nsCSSSelector& aCopy);
   nsCSSSelector& operator=(const nsCSSSelector& aCopy); 
 };
 
 /**
  * A selector list is the unit of selectors that each style rule has.
  * For example, "P B, H1 B { ... }" would be a selector list with two
--- a/layout/style/nsIStyleRuleProcessor.h
+++ b/layout/style/nsIStyleRuleProcessor.h
@@ -46,30 +46,25 @@
 #define nsIStyleRuleProcessor_h___
 
 #include "nsISupports.h"
 #include "nsChangeHint.h"
 #include "nsIContent.h"
 
 struct RuleProcessorData;
 struct ElementRuleProcessorData;
-struct PseudoElementRuleProcessorData;
-struct AnonBoxRuleProcessorData;
-#ifdef MOZ_XUL
-struct XULTreeRuleProcessorData;
-#endif
+struct PseudoRuleProcessorData;
 struct StateRuleProcessorData;
 struct AttributeRuleProcessorData;
 class nsPresContext;
 
-// IID for the nsIStyleRuleProcessor interface
-// {ec92bc0c-9518-48ea-9289-74e654659be9}
+// IID for the nsIStyleRuleProcessor interface {a4ec760e-6bfb-4b9f-bd08-9d1c23b700f6}
 #define NS_ISTYLE_RULE_PROCESSOR_IID     \
-{ 0xec92bc0c, 0x9518, 0x48ea, \
- { 0x92, 0x89, 0x74, 0xe6, 0x54, 0x65, 0x9b, 0xe9 } }
+{ 0xa4ec760e, 0x6bfb, 0x4b9f, \
+ { 0xbd, 0x08, 0x9d, 0x1c, 0x23, 0xb7, 0x00, 0xf6 } }
 
 /* The style rule processor interface is a mechanism to separate the matching
  * of style rules from style sheet instances.
  * Simple style sheets can and will act as their own processor. 
  * Sheets where rule ordering interlaces between multiple sheets, will need to 
  * share a single rule processor between them (CSS sheets do this for cascading order)
  *
  * @see nsIStyleRule (for significantly more detailed comments)
@@ -89,30 +84,17 @@ public:
    * precedence being farther from the root of the lexicographic tree).
    */
   NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData) = 0;
 
   /**
    * Just like the previous |RulesMatching|, except for a given content
    * node <em>and pseudo-element</em>.
    */
-  NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData) = 0;
-
-  /**
-   * Just like the previous |RulesMatching|, except for a given anonymous box.
-   */
-  NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData) = 0;
-
-#ifdef MOZ_XUL
-  /**
-   * Just like the previous |RulesMatching|, except for a given content
-   * node <em>and tree pseudo</em>.
-   */
-  NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData) = 0;
-#endif
+  NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData) = 0;
 
   /**
    * Return how (as described by nsReStyleHint) style can depend on a
    * change of the given content state on the given content node.  This
    * test is used for optimization only, and may err on the side of
    * reporting more dependencies than really exist.
    *
    * Event states are defined in nsIEventStateManager.h.
--- a/layout/style/nsRuleProcessorData.h
+++ b/layout/style/nsRuleProcessorData.h
@@ -43,17 +43,16 @@
 
 #ifndef nsRuleProcessorData_h_
 #define nsRuleProcessorData_h_
 
 #include "nsPresContext.h" // for nsCompatability
 #include "nsString.h"
 #include "nsChangeHint.h"
 #include "nsIContent.h"
-#include "nsCSSPseudoElements.h"
 
 class nsIStyleSheet;
 class nsPresContext;
 class nsIAtom;
 class nsICSSPseudoComparator;
 class nsRuleWalker;
 class nsAttrValue;
 
@@ -119,29 +118,29 @@ public:
   // returns 0.
   // If aCheckEdgeOnly is true, the function will return 1 if the result
   // is 1, and something other than 1 (maybe or maybe not a valid
   // result) otherwise.
   PRInt32 GetNthIndex(PRBool aIsOfType, PRBool aIsFromEnd,
                       PRBool aCheckEdgeOnly);
 
   nsPresContext*    mPresContext;
-  nsIContent*       mContent;       // weak ref, must not be null
-  nsIContent*       mParentContent; // mContent->GetParent(); weak ref
+  nsIContent*       mContent;       // weak ref
+  nsIContent*       mParentContent; // if content, content->GetParent(); weak ref
   nsRuleWalker*     mRuleWalker; // Used to add rules to our results.
   nsIContent*       mScopedRoot;    // Root of scoped stylesheet (set and unset by the supplier of the scoped stylesheet
   
-  nsIAtom*          mContentTag;    // mContent->GetTag()
-  nsIAtom*          mContentID;     // mContent->GetID()
-  PRPackedBool      mIsHTMLContent; // whether mContent it's IsHTML()
-  PRPackedBool      mIsHTML;        // mIsHTMLContent && IsInHTMLDocument()
-  PRPackedBool      mHasAttributes; // mContent->GetAttrCount() > 0
+  nsIAtom*          mContentTag;    // if content, then content->GetTag()
+  nsIAtom*          mContentID;     // if styled content, then weak reference to styledcontent->GetID()
+  PRPackedBool      mIsHTMLContent; // if content, then whether it's IsHTML()
+  PRPackedBool      mIsHTML;        // if content then mIsHTMLContent && IsInHTMLDocument()
+  PRPackedBool      mHasAttributes; // if content, content->GetAttrCount() > 0
   nsCompatibility   mCompatMode;    // Possibly remove use of this in SelectorMatches?
-  PRInt32           mNameSpaceID;   // mContent->GetNameSapce()
-  const nsAttrValue* mClasses;      // mContent->GetClasses()
+  PRInt32           mNameSpaceID;   // if content, content->GetNameSapce()
+  const nsAttrValue* mClasses;      // if styled content, styledcontent->GetClasses()
   // mPreviousSiblingData and mParentData are always RuleProcessorData
   // and never a derived class.  They are allocated lazily, when
   // selectors require matching of prior siblings or ancestors.
   RuleProcessorData* mPreviousSiblingData;
   RuleProcessorData* mParentData;
 
 private:
   nsString *mLanguage; // NULL means we haven't found out the language yet
@@ -149,103 +148,65 @@ private:
   // This node's index for :nth-child(), :nth-last-child(),
   // :nth-of-type(), :nth-last-of-type().  If -2, needs to be computed.
   // If -1, needs to be computed but known not to be 1.
   // If 0, the node is not at any index in its parent.
   // The first subscript is 0 for -child and 1 for -of-type, the second
   // subscript is 0 for nth- and 1 for nth-last-.
   PRInt32 mNthIndices[2][2];
 
-  // mContentState, mLinkState, mIsLink are initialized lazily.
-  PRInt32 mContentState;  // eventStateMgr->GetContentState() or
-                          // mContent->IntrinsicState() if we have no ESM
+  PRInt32 mContentState;  // if content, eventStateMgr->GetContentState()
   nsLinkState mLinkState; // if a link, this is the state, otherwise unknown
-  PRPackedBool mIsLink;   // nsStyleUtil::IsHTMLLink or nsStyleUtil::IsLink
+  PRPackedBool mIsLink;   // if content, calls nsStyleUtil::IsHTMLLink
+                          // or nsStyleUtil::IsLink
   PRPackedBool mGotContentState;
   PRPackedBool mGotLinkInfo; // Whether we've gotten the right values
                              // for mLinkState and mIsLink.
 };
 
 struct ElementRuleProcessorData : public RuleProcessorData {
   ElementRuleProcessorData(nsPresContext* aPresContext,
                            nsIContent* aContent, 
                            nsRuleWalker* aRuleWalker)
   : RuleProcessorData(aPresContext,aContent,aRuleWalker)
   {
     NS_PRECONDITION(aPresContext, "null pointer");
+    NS_PRECONDITION(aContent, "null pointer");
     NS_PRECONDITION(aRuleWalker, "null pointer");
   }
 };
 
-struct PseudoElementRuleProcessorData : public RuleProcessorData {
-  PseudoElementRuleProcessorData(nsPresContext* aPresContext,
-                                 nsIContent* aParentContent,
-                                 nsRuleWalker* aRuleWalker,
-                                 nsCSSPseudoElements::Type aPseudoType)
-    : RuleProcessorData(aPresContext, aParentContent, aRuleWalker),
-      mPseudoType(aPseudoType)
-  {
-    NS_PRECONDITION(aPresContext, "null pointer");
-    NS_PRECONDITION(aPseudoType <
-                      nsCSSPseudoElements::ePseudo_PseudoElementCount,
-                    "null pointer");
-    NS_PRECONDITION(aRuleWalker, "null pointer");
-  }
-
-  nsCSSPseudoElements::Type mPseudoType;
-};
-
-struct AnonBoxRuleProcessorData {
-  AnonBoxRuleProcessorData(nsPresContext* aPresContext,
-                           nsIAtom* aPseudoTag,
-                           nsRuleWalker* aRuleWalker)
-    : mPresContext(aPresContext),
-      mPseudoTag(aPseudoTag),
-      mRuleWalker(aRuleWalker)
-  {
-    NS_PRECONDITION(mPresContext, "Must have prescontext");
-    NS_PRECONDITION(aPseudoTag, "Must have pseudo tag");
-    NS_PRECONDITION(aRuleWalker, "Must have rule walker");
-  }
-
-  nsPresContext* mPresContext;
-  nsIAtom* mPseudoTag;
-  nsRuleWalker* mRuleWalker;
-};
-
-#ifdef MOZ_XUL
-struct XULTreeRuleProcessorData : public RuleProcessorData {
-  XULTreeRuleProcessorData(nsPresContext* aPresContext,
-                           nsIContent* aParentContent,
-                           nsRuleWalker* aRuleWalker,
-                           nsIAtom* aPseudoTag,
-                           nsICSSPseudoComparator* aComparator)
-    : RuleProcessorData(aPresContext, aParentContent, aRuleWalker),
-      mPseudoTag(aPseudoTag),
-      mComparator(aComparator)
+struct PseudoRuleProcessorData : public RuleProcessorData {
+  PseudoRuleProcessorData(nsPresContext* aPresContext,
+                          nsIContent* aParentContent,
+                          nsIAtom* aPseudoTag,
+                          nsICSSPseudoComparator* aComparator,
+                          nsRuleWalker* aRuleWalker)
+  : RuleProcessorData(aPresContext, aParentContent, aRuleWalker)
   {
     NS_PRECONDITION(aPresContext, "null pointer");
     NS_PRECONDITION(aPseudoTag, "null pointer");
     NS_PRECONDITION(aRuleWalker, "null pointer");
-    NS_PRECONDITION(aComparator, "must have a comparator");
+    mPseudoTag = aPseudoTag;
+    mComparator = aComparator;
   }
 
   nsIAtom*                 mPseudoTag;
   nsICSSPseudoComparator*  mComparator;
 };
-#endif
 
 struct StateRuleProcessorData : public RuleProcessorData {
   StateRuleProcessorData(nsPresContext* aPresContext,
                          nsIContent* aContent,
                          PRInt32 aStateMask)
     : RuleProcessorData(aPresContext, aContent, nsnull),
       mStateMask(aStateMask)
   {
     NS_PRECONDITION(aPresContext, "null pointer");
+    NS_PRECONDITION(aContent, "null pointer");
   }
   const PRInt32 mStateMask; // |HasStateDependentStyle| for which state(s)?
                             //  Constants defined in nsIEventStateManager.h .
 };
 
 struct AttributeRuleProcessorData : public RuleProcessorData {
   AttributeRuleProcessorData(nsPresContext* aPresContext,
                              nsIContent* aContent,
@@ -253,15 +214,16 @@ struct AttributeRuleProcessorData : publ
                              PRInt32 aModType,
                              PRBool aAttrHasChanged)
     : RuleProcessorData(aPresContext, aContent, nsnull),
       mAttribute(aAttribute),
       mModType(aModType),
       mAttrHasChanged(aAttrHasChanged)
   {
     NS_PRECONDITION(aPresContext, "null pointer");
+    NS_PRECONDITION(aContent, "null pointer");
   }
   nsIAtom* mAttribute; // |HasAttributeDependentStyle| for which attribute?
   PRInt32 mModType;    // The type of modification (see nsIDOMMutationEvent).
   PRBool mAttrHasChanged; // Whether the attribute has already changed.
 };
 
 #endif /* !defined(nsRuleProcessorData_h_) */
--- a/layout/style/nsStyleAnimation.cpp
+++ b/layout/style/nsStyleAnimation.cpp
@@ -811,17 +811,16 @@ StyleWithDeclarationAdded(nsCSSProperty 
   }
 
   // Create a temporary nsStyleContext for the style rule
   nsCOMArray<nsIStyleRule> ruleArray;
   ruleArray.AppendObject(styleRule);
   nsStyleSet* styleSet = styleContext->PresContext()->StyleSet();
   return styleSet->ResolveStyleForRules(styleContext->GetParent(),
                                         styleContext->GetPseudo(),
-                                        styleContext->GetPseudoType(),
                                         styleContext->GetRuleNode(),
                                         ruleArray);
 }
 
 PRBool
 nsStyleAnimation::ComputeValue(nsCSSProperty aProperty,
                                nsIContent* aTargetElement,
                                const nsAString& aSpecifiedValue,
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -45,41 +45,36 @@
 #include "nsIStyleRule.h"
 
 #include "nsCOMPtr.h"
 #include "nsStyleSet.h"
 #include "nsIPresShell.h"
 
 #include "nsRuleNode.h"
 #include "nsStyleContext.h"
-#include "prlog.h"
 
 #ifdef DEBUG
 // #define NOISY_DEBUG
 #endif
 
 //----------------------------------------------------------------------
 
 
 nsStyleContext::nsStyleContext(nsStyleContext* aParent,
                                nsIAtom* aPseudoTag,
-                               nsCSSPseudoElements::Type aPseudoType,
                                nsRuleNode* aRuleNode,
                                nsPresContext* aPresContext)
   : mParent(aParent),
     mChild(nsnull),
     mEmptyChild(nsnull),
     mPseudoTag(aPseudoTag),
     mRuleNode(aRuleNode),
-    mBits(((PRUint32)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT),
+    mBits(0),
     mRefCnt(0)
 {
-  PR_STATIC_ASSERT((PR_UINT32_MAX >> NS_STYLE_CONTEXT_TYPE_SHIFT) >
-                   nsCSSPseudoElements::ePseudo_MAX);
-
   mNextSibling = this;
   mPrevSibling = this;
   if (mParent) {
     mParent->AddRef();
     mParent->AddChild(this);
 #ifdef DEBUG
     nsRuleNode *r1 = mParent->GetRuleNode(), *r2 = aRuleNode;
     while (r1->GetParent())
@@ -572,20 +567,18 @@ nsStyleContext::Destroy()
   // Don't let the memory be freed, since it will be recycled
   // instead. Don't call the global operator delete.
   presContext->FreeToShell(sizeof(nsStyleContext), this);
 }
 
 already_AddRefed<nsStyleContext>
 NS_NewStyleContext(nsStyleContext* aParentContext,
                    nsIAtom* aPseudoTag,
-                   nsCSSPseudoElements::Type aPseudoType,
                    nsRuleNode* aRuleNode,
                    nsPresContext* aPresContext)
 {
-  nsStyleContext* context =
-    new (aPresContext) nsStyleContext(aParentContext, aPseudoTag, aPseudoType,
-                                      aRuleNode, aPresContext);
+  nsStyleContext* context = new (aPresContext) nsStyleContext(aParentContext, aPseudoTag, 
+                                                              aRuleNode, aPresContext);
   if (context)
     context->AddRef();
   return context;
 }
 
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -39,17 +39,16 @@
 
 /* the interface (to internal code) for retrieving computed style data */
 
 #ifndef _nsStyleContext_h_
 #define _nsStyleContext_h_
 
 #include "nsRuleNode.h"
 #include "nsIAtom.h"
-#include "nsCSSPseudoElements.h"
 
 class nsPresContext;
 
 /**
  * An nsStyleContext represents the computed style data for an element.
  * The computed style data are stored in a set of structs (see
  * nsStyleStruct.h) that are cached either on the style context or in
  * the rule tree (see nsRuleNode.h for a description of this caching and
@@ -68,18 +67,17 @@ class nsPresContext;
  *     expectation, but it makes sense in this case)
  * Style contexts participate in the mark phase of rule node garbage
  * collection.
  */
 
 class nsStyleContext
 {
 public:
-  nsStyleContext(nsStyleContext* aParent, nsIAtom* aPseudoTag,
-                 nsCSSPseudoElements::Type aPseudoType,
+  nsStyleContext(nsStyleContext* aParent, nsIAtom* aPseudoTag, 
                  nsRuleNode* aRuleNode, nsPresContext* aPresContext) NS_HIDDEN;
   ~nsStyleContext() NS_HIDDEN;
 
   NS_HIDDEN_(void*) operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW;
   NS_HIDDEN_(void) Destroy();
 
   nsrefcnt AddRef() {
     if (mRefCnt == PR_UINT32_MAX) {
@@ -105,20 +103,16 @@ public:
     return mRefCnt;
   }
 
   nsPresContext* PresContext() const { return mRuleNode->GetPresContext(); }
 
   nsStyleContext* GetParent() const { return mParent; }
 
   nsIAtom* GetPseudo() const { return mPseudoTag; }
-  nsCSSPseudoElements::Type GetPseudoType() const {
-    return static_cast<nsCSSPseudoElements::Type>(mBits >>
-                                                  NS_STYLE_CONTEXT_TYPE_SHIFT);
-  }
 
   NS_HIDDEN_(already_AddRefed<nsStyleContext>)
   FindChildWithRules(const nsIAtom* aPseudoTag, nsRuleNode* aRules);
 
   // Does this style context or any of its ancestors have text
   // decorations?
   PRBool HasTextDecorations() const
     { return !!(mBits & NS_STYLE_HAS_TEXT_DECORATIONS); }
@@ -223,12 +217,11 @@ protected:
   PRUint32                mBits; // Which structs are inherited from the
                                  // parent context.
   PRUint32                mRefCnt;
 };
 
 NS_HIDDEN_(already_AddRefed<nsStyleContext>)
 NS_NewStyleContext(nsStyleContext* aParentContext,
                    nsIAtom* aPseudoTag,
-                   nsCSSPseudoElements::Type aPseudoType,
                    nsRuleNode* aRuleNode,
                    nsPresContext* aPresContext);
 #endif
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -406,68 +406,56 @@ nsStyleSet::EnableQuirkStyleSheet(PRBool
   // (potentially implied) happens multiple times.
   if (mRuleProcessors[eAgentSheet] && aEnable != oldEnabled) {
     static_cast<nsCSSRuleProcessor*>(static_cast<nsIStyleRuleProcessor*>(
       mRuleProcessors[eAgentSheet]))->AssertQuirksChangeOK();
   }
 #endif
 }
 
-template<class T>
 static PRBool
 EnumRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
 {
-  T* data = static_cast<T*>(aData);
+  ElementRuleProcessorData* data =
+    static_cast<ElementRuleProcessorData*>(aData);
+
   aProcessor->RulesMatching(data);
   return PR_TRUE;
 }
 
 /**
  * |GetContext| implements sharing of style contexts (not just the data
  * on the rule nodes) between siblings and cousins of the same
  * generation.  (It works for cousins of the same generation since
  * |aParentContext| could itself be a shared context.)
  */
 already_AddRefed<nsStyleContext>
 nsStyleSet::GetContext(nsPresContext* aPresContext, 
                        nsStyleContext* aParentContext, 
                        nsRuleNode* aRuleNode,
-                       nsIAtom* aPseudoTag,
-                       nsCSSPseudoElements::Type aPseudoType)
+                       nsIAtom* aPseudoTag)
 {
-  NS_PRECONDITION((!aPseudoTag &&
-                   aPseudoType ==
-                     nsCSSPseudoElements::ePseudo_NotPseudoElement) ||
-                  (aPseudoTag &&
-                   nsCSSPseudoElements::GetPseudoType(aPseudoTag) ==
-                     aPseudoType),
-                  "Pseudo mismatch");
-
   nsStyleContext* result = nsnull;
       
   if (aParentContext)
     result = aParentContext->FindChildWithRules(aPseudoTag, aRuleNode).get();
 
 #ifdef NOISY_DEBUG
   if (result)
     fprintf(stdout, "--- SharedSC %d ---\n", ++gSharedCount);
   else
     fprintf(stdout, "+++ NewSC %d +++\n", ++gNewCount);
 #endif
 
   if (!result) {
-    result = NS_NewStyleContext(aParentContext, aPseudoTag, aPseudoType,
-                                aRuleNode, aPresContext).get();
+    result = NS_NewStyleContext(aParentContext, aPseudoTag, aRuleNode,
+                                aPresContext).get();
     if (!aParentContext && result)
       mRoots.AppendElement(result);
   }
-  else {
-    NS_ASSERTION(result->GetPseudoType() == aPseudoType, "Unexpected type");
-    NS_ASSERTION(result->GetPseudo() == aPseudoTag, "Unexpected pseudo");
-  }
 
   return result;
 }
 
 void
 nsStyleSet::AddImportantRules(nsRuleNode* aCurrLevelNode,
                               nsRuleNode* aLastPrevLevelNode,
                               nsRuleWalker* aRuleWalker)
@@ -525,18 +513,17 @@ nsStyleSet::AssertNoCSSRules(nsRuleNode*
     NS_ASSERTION(!cssRule || !cssRule->Selector(), "Unexpected CSS rule");
   }
 }
 #endif
 
 // Enumerate the rules in a way that cares about the order of the rules.
 void
 nsStyleSet::FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, 
-                      void* aData, nsIContent* aContent,
-                      nsRuleWalker* aRuleWalker)
+                      RuleProcessorData* aData, nsRuleWalker* aRuleWalker)
 {
   // Cascading order:
   // [least important]
   //  1. UA normal rules                    = Agent        normal
   //  2. Presentation hints                 = PresHint     normal
   //  3. User normal rules                  = User         normal
   //  4. HTML Presentation hints            = HTMLPresHint normal
   //  5. Author normal rules                = Document     normal
@@ -559,34 +546,32 @@ nsStyleSet::FileRules(nsIStyleRuleProces
 
   aRuleWalker->SetLevel(ePresHintSheet, PR_FALSE, PR_FALSE);
   if (mRuleProcessors[ePresHintSheet])
     (*aCollectorFunc)(mRuleProcessors[ePresHintSheet], aData);
   nsRuleNode* lastPresHintRN = aRuleWalker->GetCurrentNode();
 
   aRuleWalker->SetLevel(eUserSheet, PR_FALSE, PR_TRUE);
   PRBool skipUserStyles =
-    aContent && aContent->IsInNativeAnonymousSubtree();
+    aData->mContent && aData->mContent->IsInNativeAnonymousSubtree();
   if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different
     (*aCollectorFunc)(mRuleProcessors[eUserSheet], aData);
   nsRuleNode* lastUserRN = aRuleWalker->GetCurrentNode();
   PRBool haveImportantUserRules = !aRuleWalker->GetCheckForImportantRules();
 
   aRuleWalker->SetLevel(eHTMLPresHintSheet, PR_FALSE, PR_FALSE);
   if (mRuleProcessors[eHTMLPresHintSheet])
     (*aCollectorFunc)(mRuleProcessors[eHTMLPresHintSheet], aData);
   nsRuleNode* lastHTMLPresHintRN = aRuleWalker->GetCurrentNode();
   
   aRuleWalker->SetLevel(eDocSheet, PR_FALSE, PR_TRUE);
   PRBool cutOffInheritance = PR_FALSE;
-  if (mBindingManager && aContent) {
+  if (mBindingManager) {
     // We can supply additional document-level sheets that should be walked.
-    mBindingManager->WalkRules(aCollectorFunc,
-                               static_cast<RuleProcessorData*>(aData),
-                               &cutOffInheritance);
+    mBindingManager->WalkRules(aCollectorFunc, aData, &cutOffInheritance);
   }
   if (!skipUserStyles && !cutOffInheritance &&
       mRuleProcessors[eDocSheet]) // NOTE: different
     (*aCollectorFunc)(mRuleProcessors[eDocSheet], aData);
   aRuleWalker->SetLevel(eStyleAttrSheet, PR_FALSE,
                         aRuleWalker->GetCheckForImportantRules());
   if (mRuleProcessors[eStyleAttrSheet])
     (*aCollectorFunc)(mRuleProcessors[eStyleAttrSheet], aData);
@@ -671,17 +656,18 @@ nsStyleSet::WalkRuleProcessors(nsIStyleR
                   SheetCount(eHTMLPresHintSheet) == 0,
                   "Can't have both types of preshint sheets at once!");
   
   if (mRuleProcessors[eAgentSheet])
     (*aFunc)(mRuleProcessors[eAgentSheet], aData);
   if (mRuleProcessors[ePresHintSheet])
     (*aFunc)(mRuleProcessors[ePresHintSheet], aData);
 
-  PRBool skipUserStyles = aData->mContent->IsInNativeAnonymousSubtree();
+  PRBool skipUserStyles =
+    aData->mContent && aData->mContent->IsInNativeAnonymousSubtree();
   if (!skipUserStyles && mRuleProcessors[eUserSheet]) // NOTE: different
     (*aFunc)(mRuleProcessors[eUserSheet], aData);
 
   if (mRuleProcessors[eHTMLPresHintSheet])
     (*aFunc)(mRuleProcessors[eHTMLPresHintSheet], aData);
   
   PRBool cutOffInheritance = PR_FALSE;
   if (mBindingManager) {
@@ -742,30 +728,27 @@ nsStyleSet::ResolveStyleFor(nsIContent* 
 
   NS_ASSERTION(aContent, "must have content");
   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eELEMENT),
                "content must be element");
 
   if (aContent && presContext) {
     nsRuleWalker ruleWalker(mRuleTree);
     ElementRuleProcessorData data(presContext, aContent, &ruleWalker);
-    FileRules(EnumRulesMatching<ElementRuleProcessorData>, &data, aContent,
-              &ruleWalker);
+    FileRules(EnumRulesMatching, &data, &ruleWalker);
     result = GetContext(presContext, aParentContext,
-                        ruleWalker.GetCurrentNode(), nsnull,
-                        nsCSSPseudoElements::ePseudo_NotPseudoElement).get();
+                        ruleWalker.GetCurrentNode(), nsnull).get();
   }
 
   return result;
 }
 
 already_AddRefed<nsStyleContext>
 nsStyleSet::ResolveStyleForRules(nsStyleContext* aParentContext,
                                  nsIAtom* aPseudoTag,
-                                 nsCSSPseudoElements::Type aPseudoType,
                                  nsRuleNode *aRuleNode,
                                  const nsCOMArray<nsIStyleRule> &aRules)
 {
   NS_ENSURE_FALSE(mInShutdown, nsnull);
   nsStyleContext* result = nsnull;
   nsPresContext *presContext = PresContext();
 
   if (presContext) {
@@ -774,179 +757,152 @@ nsStyleSet::ResolveStyleForRules(nsStyle
       ruleWalker.SetCurrentNode(aRuleNode);
     // FIXME: Perhaps this should be passed in, but it probably doesn't
     // matter.
     ruleWalker.SetLevel(eDocSheet, PR_FALSE, PR_FALSE);
     for (PRInt32 i = 0; i < aRules.Count(); i++) {
       ruleWalker.Forward(aRules.ObjectAt(i));
     }
     result = GetContext(presContext, aParentContext,
-                        ruleWalker.GetCurrentNode(), aPseudoTag,
-                        aPseudoType).get();
+                        ruleWalker.GetCurrentNode(), aPseudoTag).get();
   }
   return result;
 }
 
 already_AddRefed<nsStyleContext>
 nsStyleSet::ResolveStyleForNonElement(nsStyleContext* aParentContext)
 {
   nsStyleContext* result = nsnull;
   nsPresContext *presContext = PresContext();
 
   if (presContext) {
     result = GetContext(presContext, aParentContext, mRuleTree,
-                        nsCSSAnonBoxes::mozNonElement,
-                        nsCSSPseudoElements::ePseudo_AnonBox).get();
+                        nsCSSAnonBoxes::mozNonElement).get();
   }
 
   return result;
 }
 
 void
-nsStyleSet::WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType,
+nsStyleSet::WalkRestrictionRule(nsIAtom* aPseudoType,
                                 nsRuleWalker* aRuleWalker)
 {
   // This needs to match GetPseudoRestriction in nsRuleNode.cpp.
-  aRuleWalker->SetLevel(eAgentSheet, PR_FALSE, PR_FALSE);
-  if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLetter)
-    aRuleWalker->Forward(mFirstLetterRule);
-  else if (aPseudoType == nsCSSPseudoElements::ePseudo_firstLine)
-    aRuleWalker->Forward(mFirstLineRule);
+  if (aPseudoType) {
+    aRuleWalker->SetLevel(eAgentSheet, PR_FALSE, PR_FALSE);
+    if (aPseudoType == nsCSSPseudoElements::firstLetter)
+      aRuleWalker->Forward(mFirstLetterRule);
+    else if (aPseudoType == nsCSSPseudoElements::firstLine)
+      aRuleWalker->Forward(mFirstLineRule);
+  }
+}
+
+static PRBool
+EnumPseudoRulesMatching(nsIStyleRuleProcessor* aProcessor, void* aData)
+{
+  PseudoRuleProcessorData* data =
+    static_cast<PseudoRuleProcessorData*>(aData);
+
+  aProcessor->RulesMatching(data);
+  return PR_TRUE;
 }
 
 already_AddRefed<nsStyleContext>
-nsStyleSet::ResolvePseudoElementStyle(nsIContent* aParentContent,
-                                      nsCSSPseudoElements::Type aType,
-                                      nsStyleContext* aParentContext)
+nsStyleSet::ResolvePseudoStyleFor(nsIContent* aParentContent,
+                                  nsIAtom* aPseudoTag,
+                                  nsStyleContext* aParentContext,
+                                  nsICSSPseudoComparator* aComparator)
 {
   NS_ENSURE_FALSE(mInShutdown, nsnull);
 
-  NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount,
-               "must have pseudo element type");
+  nsStyleContext*  result = nsnull;
+  nsPresContext *presContext = PresContext();
+
+  NS_ASSERTION(aPseudoTag, "must have pseudo tag");
+  NS_ASSERTION(!aParentContent ||
+               aParentContent->IsNodeOfType(nsINode::eELEMENT),
+               "content (if non-null) must be element");
+  NS_ASSERTION(aParentContent ||
+               nsCSSAnonBoxes::IsAnonBox(aPseudoTag),
+               "null content must correspond to anonymous box");
+  NS_ASSERTION(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) ||
+               nsCSSPseudoElements::IsPseudoElement(aPseudoTag),
+               "aPseudoTag must be pseudo-element or anonymous box");
+
+  if (aPseudoTag && presContext) {
+    nsRuleWalker ruleWalker(mRuleTree);
+    PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag,
+                                 aComparator, &ruleWalker);
+    WalkRestrictionRule(aPseudoTag, &ruleWalker);
+    FileRules(EnumPseudoRulesMatching, &data, &ruleWalker);
+
+    result = GetContext(presContext, aParentContext,
+                        ruleWalker.GetCurrentNode(), aPseudoTag).get();
+  }
+
+  return result;
+}
+
+already_AddRefed<nsStyleContext>
+nsStyleSet::ProbePseudoStyleFor(nsIContent* aParentContent,
+                                nsIAtom* aPseudoTag,
+                                nsStyleContext* aParentContext)
+{
+  NS_ENSURE_FALSE(mInShutdown, nsnull);
+  
+  nsStyleContext*  result = nsnull;
+  nsPresContext *presContext = PresContext();
+
+  NS_ASSERTION(aPseudoTag, "must have pseudo tag");
   NS_ASSERTION(aParentContent &&
                aParentContent->IsNodeOfType(nsINode::eELEMENT),
                "aParentContent must be element");
-
-  nsRuleWalker ruleWalker(mRuleTree);
-  nsPresContext *presContext = PresContext();
-  PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker,
-                                      aType);
-  WalkRestrictionRule(aType, &ruleWalker);
-  FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
-            aParentContent, &ruleWalker);
-
-  return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(),
-                    nsCSSPseudoElements::GetPseudoAtom(aType), aType);
-}
+  //NS_ASSERTION(nsCSSPseudoElements::IsPseudoElement(aPseudoTag),
+  //             "aPseudoTag must be a pseudo-element");
+  NS_ASSERTION(aParentContent ||
+               nsCSSAnonBoxes::IsAnonBox(aPseudoTag),
+               "null content must correspond to anonymous box");
+  NS_ASSERTION(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) ||
+               nsCSSPseudoElements::IsPseudoElement(aPseudoTag),
+               "aPseudoTag must be pseudo-element or anonymous box");
 
-already_AddRefed<nsStyleContext>
-nsStyleSet::ProbePseudoElementStyle(nsIContent* aParentContent,
-                                    nsCSSPseudoElements::Type aType,
-                                    nsStyleContext* aParentContext)
-{
-  NS_ENSURE_FALSE(mInShutdown, nsnull);
-  
-  NS_ASSERTION(aType < nsCSSPseudoElements::ePseudo_PseudoElementCount,
-               "must have pseudo element type");
-  NS_ASSERTION(aParentContent &&
-               aParentContent->IsNodeOfType(nsINode::eELEMENT),
-               "aParentContent must be element");
-
-  nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
-
-  nsPresContext *presContext = PresContext();
+  if (aPseudoTag && presContext) {
+    nsRuleWalker ruleWalker(mRuleTree);
+    PseudoRuleProcessorData data(presContext, aParentContent, aPseudoTag,
+                                 nsnull, &ruleWalker);
+    WalkRestrictionRule(aPseudoTag, &ruleWalker);
+    // not the root if there was a restriction rule
+    nsRuleNode *adjustedRoot = ruleWalker.GetCurrentNode();
+    FileRules(EnumPseudoRulesMatching, &data, &ruleWalker);
 
-  nsRuleWalker ruleWalker(mRuleTree);
-  PseudoElementRuleProcessorData data(presContext, aParentContent, &ruleWalker,
-                                      aType);
-  WalkRestrictionRule(aType, &ruleWalker);
-  // not the root if there was a restriction rule
-  nsRuleNode *adjustedRoot = ruleWalker.GetCurrentNode();
-  FileRules(EnumRulesMatching<PseudoElementRuleProcessorData>, &data,
-            aParentContent, &ruleWalker);
-
-  nsRuleNode *ruleNode = ruleWalker.GetCurrentNode();
-  if (ruleNode == adjustedRoot) {
-    return nsnull;
+    nsRuleNode *ruleNode = ruleWalker.GetCurrentNode();
+    if (ruleNode != adjustedRoot)
+      result =
+        GetContext(presContext, aParentContext, ruleNode, aPseudoTag).get();
   }
 
-  nsRefPtr<nsStyleContext> result =
-    GetContext(presContext, aParentContext, ruleNode, pseudoTag, aType);
-
   // For :before and :after pseudo-elements, having display: none or no
   // 'content' property is equivalent to not having the pseudo-element
   // at all.
   if (result &&
-      (pseudoTag == nsCSSPseudoElements::before ||
-       pseudoTag == nsCSSPseudoElements::after)) {
+      (aPseudoTag == nsCSSPseudoElements::before ||
+       aPseudoTag == nsCSSPseudoElements::after)) {
     const nsStyleDisplay *display = result->GetStyleDisplay();
     const nsStyleContent *content = result->GetStyleContent();
     // XXXldb What is contentCount for |content: ""|?
     if (display->mDisplay == NS_STYLE_DISPLAY_NONE ||
         content->ContentCount() == 0) {
+      result->Release();
       result = nsnull;
     }
   }
   
-  return result.forget();
-}
-
-already_AddRefed<nsStyleContext>
-nsStyleSet::ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag,
-                                     nsStyleContext* aParentContext)
-{
-  NS_ENSURE_FALSE(mInShutdown, nsnull);
-
-#ifdef DEBUG
-    PRBool isAnonBox = nsCSSAnonBoxes::IsAnonBox(aPseudoTag)
-#ifdef MOZ_XUL
-                 && !nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag)
-#endif
-      ;
-    NS_PRECONDITION(isAnonBox, "Unexpected pseudo");
-#endif
-
-  nsRuleWalker ruleWalker(mRuleTree);
-  nsPresContext *presContext = PresContext();
-  AnonBoxRuleProcessorData data(presContext, aPseudoTag, &ruleWalker);
-  FileRules(EnumRulesMatching<AnonBoxRuleProcessorData>, &data, nsnull,
-            &ruleWalker);
-
-  return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(),
-                    aPseudoTag, nsCSSPseudoElements::ePseudo_AnonBox);
+  return result;
 }
 
-#ifdef MOZ_XUL
-already_AddRefed<nsStyleContext>
-nsStyleSet::ResolveXULTreePseudoStyle(nsIContent* aParentContent,
-                                      nsIAtom* aPseudoTag,
-                                      nsStyleContext* aParentContext,
-                                      nsICSSPseudoComparator* aComparator)
-{
-  NS_ENSURE_FALSE(mInShutdown, nsnull);
-
-  NS_ASSERTION(aPseudoTag, "must have pseudo tag");
-  NS_ASSERTION(aParentContent->IsNodeOfType(nsINode::eELEMENT),
-               "content (if non-null) must be element");
-  NS_ASSERTION(nsCSSAnonBoxes::IsTreePseudoElement(aPseudoTag),
-               "Unexpected pseudo");
-
-  nsRuleWalker ruleWalker(mRuleTree);
-  nsPresContext *presContext = PresContext();
-
-  XULTreeRuleProcessorData data(presContext, aParentContent, &ruleWalker,
-                                aPseudoTag, aComparator);
-  FileRules(EnumRulesMatching<XULTreeRuleProcessorData>, &data, aParentContent,
-            &ruleWalker);
-
-  return GetContext(presContext, aParentContext, ruleWalker.GetCurrentNode(),
-                    aPseudoTag, nsCSSPseudoElements::ePseudo_XULTree);
-}
-#endif
-
 PRBool
 nsStyleSet::AppendFontFaceRules(nsPresContext* aPresContext,
                                 nsTArray<nsFontFaceRuleContainer>& aArray)
 {
   NS_ENSURE_FALSE(mInShutdown, PR_FALSE);
 
   for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(gCSSSheetTypes); ++i) {
     nsCSSRuleProcessor *ruleProc = static_cast<nsCSSRuleProcessor*>
@@ -1047,22 +1003,20 @@ nsStyleSet::ReParentStyleContext(nsPresC
 
   if (aPresContext && aStyleContext) {
     if (aStyleContext->GetParent() == aNewParentContext) {
       aStyleContext->AddRef();
       return aStyleContext;
     }
     else {  // really a new parent
       nsIAtom* pseudoTag = aStyleContext->GetPseudo();
-      nsCSSPseudoElements::Type pseudoType = aStyleContext->GetPseudoType();
       nsRuleNode* ruleNode = aStyleContext->GetRuleNode();
 
       already_AddRefed<nsStyleContext> result =
-        GetContext(aPresContext, aNewParentContext, ruleNode, pseudoTag,
-                   pseudoType);
+          GetContext(aPresContext, aNewParentContext, ruleNode, pseudoTag);
       return result;
     }
   }
   return nsnull;
 }
 
 struct StatefulData : public StateRuleProcessorData {
   StatefulData(nsPresContext* aPresContext,
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -50,18 +50,16 @@
 #include "nsIStyleRuleProcessor.h"
 #include "nsICSSStyleSheet.h"
 #include "nsBindingManager.h"
 #include "nsRuleNode.h"
 #include "nsTArray.h"
 #include "nsCOMArray.h"
 #include "nsAutoPtr.h"
 #include "nsIStyleRule.h"
-#include "nsCSSPseudoElements.h"
-#include "nsCSSAnonBoxes.h"
 
 class nsIURI;
 class nsCSSFontFaceRule;
 class nsRuleWalker;
 struct RuleProcessorData;
 
 class nsEmptyStyleRule : public nsIStyleRule
 {
@@ -94,69 +92,54 @@ class nsStyleSet
 
   // enable / disable the Quirk style sheet
   void EnableQuirkStyleSheet(PRBool aEnable);
 
   // get a style context for a non-pseudo frame.
   already_AddRefed<nsStyleContext>
   ResolveStyleFor(nsIContent* aContent, nsStyleContext* aParentContext);
 
-  // Get a style context (with the given parent and pseudo-tag/type) for a
+  // Get a style context (with the given parent and pseudo-tag) for a
   // sequence of style rules consisting of the concatenation of:
   //  (1) the rule sequence represented by aRuleNode (which is the empty
   //      sequence if aRuleNode is null or the root of the rule tree), and
   //  (2) the rules in the |aRules| array.
   already_AddRefed<nsStyleContext>
   ResolveStyleForRules(nsStyleContext* aParentContext,
                        nsIAtom* aPseudoTag,
-                       nsCSSPseudoElements::Type aPseudoType,
                        nsRuleNode *aRuleNode,
                        const nsCOMArray<nsIStyleRule> &aRules);
 
   // Get a style context for a non-element (which no rules will match),
   // such as text nodes, placeholder frames, and the nsFirstLetterFrame
   // for everything after the first letter.
   //
   // Perhaps this should go away and we shouldn't even create style
   // contexts for such content nodes.  However, not doing any rule
   // matching for them is a first step.
   already_AddRefed<nsStyleContext>
   ResolveStyleForNonElement(nsStyleContext* aParentContext);
 
-  // Get a style context for a pseudo-element.  aParentContent must be
-  // non-null.  aPseudoID is the nsCSSPseudoElements::Type for the
-  // pseudo-element.
-  already_AddRefed<nsStyleContext>
-  ResolvePseudoElementStyle(nsIContent* aParentContent,
-                            nsCSSPseudoElements::Type aType,
-                            nsStyleContext* aParentContext);
-
-  // This functions just like ResolvePseudoElementStyle except that it will
-  // return nsnull if there are no explicit style rules for that
-  // pseudo element.
+  // get a style context for a pseudo-element (i.e.,
+  // |aPseudoTag == nsCOMPtr<nsIAtom>(do_GetAtom(":first-line"))|, in
+  // which case aParentContent must be non-null, or an anonymous box, in
+  // which case it may be null or non-null.
   already_AddRefed<nsStyleContext>
-  ProbePseudoElementStyle(nsIContent* aParentContent,
-                          nsCSSPseudoElements::Type aType,
-                          nsStyleContext* aParentContext);
-  
-  // Get a style context for an anonymous box.  aPseudoTag is the
-  // pseudo-tag to use and must be non-null.
-  already_AddRefed<nsStyleContext>
-  ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext);
+  ResolvePseudoStyleFor(nsIContent* aParentContent,
+                        nsIAtom* aPseudoTag,
+                        nsStyleContext* aParentContext,
+                        nsICSSPseudoComparator* aComparator = nsnull);
 
-#ifdef MOZ_XUL
-  // Get a style context for a XUL tree pseudo.  aPseudoTag is the
-  // pseudo-tag to use and must be non-null.  aParentContent must be
-  // non-null.  aComparator must be non-null.
+  // This functions just like ResolvePseudoStyleFor except that it will
+  // return nsnull if there are no explicit style rules for that
+  // pseudo element.  It should be used only for pseudo-elements.
   already_AddRefed<nsStyleContext>
-  ResolveXULTreePseudoStyle(nsIContent* aParentContent,
-                            nsIAtom* aPseudoTag,
-                            nsStyleContext* aParentContext,
-                            nsICSSPseudoComparator* aComparator);
-#endif
+  ProbePseudoStyleFor(nsIContent* aParentContent,
+                      nsIAtom* aPseudoTag,
+                      nsStyleContext* aParentContext);
 
   // Append all the currently-active font face rules to aArray.  Return
   // true for success and false for failure.
   PRBool AppendFontFaceRules(nsPresContext* aPresContext,
                              nsTArray<nsFontFaceRuleContainer>& aArray);
 
   // Begin ignoring style context destruction, to avoid lots of unnecessary
   // work on document teardown.
@@ -293,17 +276,17 @@ class nsStyleSet
   nsresult GatherRuleProcessors(sheetType aType);
 
   void AddImportantRules(nsRuleNode* aCurrLevelNode,
                          nsRuleNode* aLastPrevLevelNode,
                          nsRuleWalker* aRuleWalker);
 
   // Move aRuleWalker forward by the appropriate rule if we need to add
   // a rule due to property restrictions on pseudo-elements.
-  void WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType,
+  void WalkRestrictionRule(nsIAtom* aPseudoType,
                            nsRuleWalker* aRuleWalker);
 
 #ifdef DEBUG
   // Just like AddImportantRules except it doesn't actually add anything; it
   // just asserts that there are no important rules between aCurrLevelNode and
   // aLastPrevLevelNode.
   void AssertNoImportantRules(nsRuleNode* aCurrLevelNode,
                               nsRuleNode* aLastPrevLevelNode);
@@ -312,32 +295,28 @@ class nsStyleSet
   // just asserts that there are no CSS rules between aCurrLevelNode and
   // aLastPrevLevelNode.  Mostly useful for the preshint levels.
   void AssertNoCSSRules(nsRuleNode* aCurrLevelNode,
                         nsRuleNode* aLastPrevLevelNode);
 #endif
   
   // Enumerate the rules in a way that cares about the order of the
   // rules.
-  // aContent is the node the rules are for.  It might be null.  aData
-  // is the closure to pass to aCollectorFunc.  If aContent is not null,
-  // aData must be a RuleProcessorData*
   void FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc,
-                 void* aData, nsIContent* aContent, nsRuleWalker* aRuleWalker);
+                 RuleProcessorData* aData, nsRuleWalker* aRuleWalker);
 
   // Enumerate all the rules in a way that doesn't care about the order
   // of the rules and break out if the enumeration is halted.
   void WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc,
                           RuleProcessorData* aData);
 
   already_AddRefed<nsStyleContext> GetContext(nsPresContext* aPresContext,
                                               nsStyleContext* aParentContext,
                                               nsRuleNode* aRuleNode,
-                                              nsIAtom* aPseudoTag,
-                                              nsCSSPseudoElements::Type aPseudoType);
+                                              nsIAtom* aPseudoTag);
 
   nsPresContext* PresContext() { return mRuleTree->GetPresContext(); }
 
   // The sheets in each array in mSheets are stored with the most significant
   // sheet last.
   nsCOMArray<nsIStyleSheet> mSheets[eSheetTypeCount];
 
   nsCOMPtr<nsIStyleRuleProcessor> mRuleProcessors[eSheetTypeCount];
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -78,19 +78,16 @@ class imgIContainer;
 // NS_STYLE_INHERIT_BIT defined in nsStyleStructFwd.h
 #define NS_STYLE_INHERIT_MASK             0x00ffffff
 
 // Additional bits for nsStyleContext's mBits:
 // See nsStyleContext::HasTextDecorations
 #define NS_STYLE_HAS_TEXT_DECORATIONS     0x01000000
 // See nsStyleContext::HasPseudoElementData.
 #define NS_STYLE_HAS_PSEUDO_ELEMENT_DATA  0x02000000
-// See nsStyleContext::GetPseudoEnum
-#define NS_STYLE_CONTEXT_TYPE_MASK        0xf0000000
-#define NS_STYLE_CONTEXT_TYPE_SHIFT       28
 
 // Additional bits for nsRuleNode's mDependentBits:
 #define NS_RULE_NODE_GC_MARK              0x02000000
 #define NS_RULE_NODE_IS_IMPORTANT         0x08000000
 #define NS_RULE_NODE_LEVEL_MASK           0xf0000000
 #define NS_RULE_NODE_LEVEL_SHIFT          28
 
 // The lifetime of these objects is managed by the presshell's arena.
--- a/layout/style/nsTransitionManager.cpp
+++ b/layout/style/nsTransitionManager.cpp
@@ -44,16 +44,17 @@
 #include "mozilla/TimeStamp.h"
 #include "nsRefreshDriver.h"
 #include "nsRuleProcessorData.h"
 #include "nsIStyleRule.h"
 #include "nsRuleWalker.h"
 #include "nsRuleData.h"
 #include "nsSMILKeySpline.h"
 #include "gfxColor.h"
+#include "nsCSSPseudoElements.h"
 #include "nsCSSPropertySet.h"
 #include "nsStyleAnimation.h"
 #include "nsCSSDataBlock.h"
 
 using mozilla::TimeStamp;
 using mozilla::TimeDuration;
 
 /*****************************************************************************
@@ -367,20 +368,19 @@ nsTransitionManager::StyleContextChanged
     return nsnull;
   }      
 
 
   if (aNewStyleContext->PresContext()->IsProcessingAnimationStyleChange()) {
     return nsnull;
   }
   
-  nsCSSPseudoElements::Type pseudoType = aNewStyleContext->GetPseudoType();
-  if (pseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement &&
-      pseudoType != nsCSSPseudoElements::ePseudo_before &&
-      pseudoType != nsCSSPseudoElements::ePseudo_after) {
+  nsIAtom *pseudo = aNewStyleContext->GetPseudo();
+  if (pseudo && (pseudo != nsCSSPseudoElements::before &&
+                 pseudo != nsCSSPseudoElements::after)) {
     return nsnull;
   }
   if (aNewStyleContext->GetParent() &&
       aNewStyleContext->GetParent()->HasPseudoElementData()) {
     // Ignore transitions on things that inherit properties from
     // pseudo-elements.
     // FIXME (Bug 522599): Add tests for this.
     return nsnull;
@@ -393,17 +393,19 @@ nsTransitionManager::StyleContextChanged
   PRBool startedAny = PR_FALSE;
   nsCSSPropertySet whichStarted;
   ElementTransitions *et = nsnull;
   for (PRUint32 i = disp->mTransitionPropertyCount; i-- != 0; ) {
     const nsTransition& t = disp->mTransitions[i];
     // Check delay and duration first, since they default to zero, and
     // when they're both zero, we can ignore the transition.
     if (t.GetDelay() != 0.0f || t.GetDuration() != 0.0f) {
-      et = GetElementTransitions(aElement, pseudoType, PR_FALSE);
+      et = GetElementTransitions(aElement,
+                                 aNewStyleContext->GetPseudo(),
+                                 PR_FALSE);
 
       // We might have something to transition.  See if any of the
       // properties in question changed and are animatable.
       nsCSSProperty property = t.GetProperty();
       if (property == eCSSPropertyExtra_no_properties ||
           property == eCSSProperty_UNKNOWN) {
         // Nothing to do, but need to exclude this from cases below.
       } else if (property == eCSSPropertyExtra_all_properties) {
@@ -607,17 +609,17 @@ nsTransitionManager::ConsiderStartingTra
   pt.mStartTime = rd->MostRecentRefresh() +
                   TimeDuration::FromMilliseconds(delay);
   pt.mDuration = TimeDuration::FromMilliseconds(duration);
   const nsTimingFunction &tf = aTransition.GetTimingFunction();
   pt.mTimingFunction.Init(tf.mX1, tf.mY1, tf.mX2, tf.mY2);
 
   if (!aElementTransitions) {
     aElementTransitions =
-      GetElementTransitions(aElement, aNewStyleContext->GetPseudoType(),
+      GetElementTransitions(aElement, aNewStyleContext->GetPseudo(),
                             PR_TRUE);
     if (!aElementTransitions) {
       NS_WARNING("allocating ElementTransitions failed");
       return;
     }
   }
   
   nsTArray<ElementPropertyTransition> &pts =
@@ -641,27 +643,26 @@ nsTransitionManager::ConsiderStartingTra
   presContext->PresShell()->RestyleForAnimation(aElement);
 
   *aStartedAny = PR_TRUE;
   aWhichStarted->AddProperty(aProperty);
 }
 
 ElementTransitions*
 nsTransitionManager::GetElementTransitions(nsIContent *aElement,
-                                           nsCSSPseudoElements::Type aPseudoType,
+                                           nsIAtom *aPseudo,
                                            PRBool aCreateIfNeeded)
 {
   nsIAtom *propName;
-  if (aPseudoType == nsCSSPseudoElements::ePseudo_before) {
+  if (aPseudo == nsCSSPseudoElements::before) {
     propName = nsGkAtoms::transitionsOfBeforeProperty;
-  } else if (aPseudoType == nsCSSPseudoElements::ePseudo_after) {
+  } else if (aPseudo == nsCSSPseudoElements::after) {
     propName = nsGkAtoms::transitionsOfAfterProperty;
   } else {
-    NS_ASSERTION(aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement ||
-		 !aCreateIfNeeded,
+    NS_ASSERTION(!aPseudo || !aCreateIfNeeded,
                  "should never try to create transitions for pseudo "
                  "other than :before or :after");
     propName = nsGkAtoms::transitionsProperty;
   }
   ElementTransitions *et = static_cast<ElementTransitions*>(
                              aElement->GetProperty(propName));
   if (!et && aCreateIfNeeded) {
     // FIXME: Consider arena-allocating?
@@ -705,32 +706,32 @@ NS_IMPL_RELEASE_USING_AGGREGATOR(nsTrans
 NS_IMPL_QUERY_INTERFACE1(nsTransitionManager, nsIStyleRuleProcessor)
 
 /*
  * nsIStyleRuleProcessor implementation
  */
 
 nsresult
 nsTransitionManager::WalkTransitionRule(RuleProcessorData* aData,
-                                        nsCSSPseudoElements::Type aPseudoType)
+                                        nsIAtom *aPseudo)
 {
   if (!aData->mPresContext->IsProcessingAnimationStyleChange()) {
     // If we're processing a normal style change rather than one from
     // animation, don't add the transition rule.  This allows us to
     // compute the new style value rather than having the transition
     // override it, so that we can start transitioning differently.
 
     // In most cases, we need to immediately restyle with animation
     // after doing this.  However, ConsiderStartingTransition takes care
     // of that for us.
     return NS_OK;
   }
 
   ElementTransitions *et =
-    GetElementTransitions(aData->mContent, aPseudoType, PR_FALSE);
+    GetElementTransitions(aData->mContent, aPseudo, PR_FALSE);
   if (!et) {
     return NS_OK;
   }
 
   if (!et->EnsureStyleRuleFor(
         aData->mPresContext->RefreshDriver()->MostRecentRefresh())) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -740,46 +741,30 @@ nsTransitionManager::WalkTransitionRule(
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTransitionManager::RulesMatching(ElementRuleProcessorData* aData)
 {
   NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
                     "pres context mismatch");
-  return WalkTransitionRule(aData,
-			    nsCSSPseudoElements::ePseudo_NotPseudoElement);
+  return WalkTransitionRule(aData, nsnull);
 }
 
 NS_IMETHODIMP
-nsTransitionManager::RulesMatching(PseudoElementRuleProcessorData* aData)
+nsTransitionManager::RulesMatching(PseudoRuleProcessorData* aData)
 {
   NS_ABORT_IF_FALSE(aData->mPresContext == mPresContext,
                     "pres context mismatch");
-
   // Note:  If we're the only thing keeping a pseudo-element frame alive
   // (per ProbePseudoStyleContext), we still want to keep it alive, so
   // this is ok.
-  return WalkTransitionRule(aData, aData->mPseudoType);
-}
-
-NS_IMETHODIMP
-nsTransitionManager::RulesMatching(AnonBoxRuleProcessorData* aData)
-{
-  return NS_OK;
+  return WalkTransitionRule(aData, aData->mPseudoTag);
 }
 
-#ifdef MOZ_XUL
-NS_IMETHODIMP
-nsTransitionManager::RulesMatching(XULTreeRuleProcessorData* aData)
-{
-  return NS_OK;
-}
-#endif
-
 NS_IMETHODIMP
 nsTransitionManager::HasStateDependentStyle(StateRuleProcessorData* aData,
                                             nsReStyleHint* aResult)
 {
   *aResult = nsReStyleHint(0);
   return NS_OK;
 }
 
--- a/layout/style/nsTransitionManager.h
+++ b/layout/style/nsTransitionManager.h
@@ -39,17 +39,16 @@
 
 #ifndef nsTransitionManager_h_
 #define nsTransitionManager_h_
 
 #include "prclist.h"
 #include "nsCSSProperty.h"
 #include "nsIStyleRuleProcessor.h"
 #include "nsRefreshDriver.h"
-#include "nsCSSPseudoElements.h"
 
 class nsStyleContext;
 class nsPresContext;
 class nsCSSPropertySet;
 struct nsTransition;
 struct ElementTransitions;
 
 /**
@@ -81,21 +80,17 @@ public:
                         nsStyleContext *aOldStyleContext,
                         nsStyleContext *aNewStyleContext);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIStyleRuleProcessor
   NS_IMETHOD RulesMatching(ElementRuleProcessorData* aData);
-  NS_IMETHOD RulesMatching(PseudoElementRuleProcessorData* aData);
-  NS_IMETHOD RulesMatching(AnonBoxRuleProcessorData* aData);
-#ifdef MOZ_XUL
-  NS_IMETHOD RulesMatching(XULTreeRuleProcessorData* aData);
-#endif
+  NS_IMETHOD RulesMatching(PseudoRuleProcessorData* aData);
   NS_IMETHOD HasStateDependentStyle(StateRuleProcessorData* aData,
                                     nsReStyleHint* aResult);
   virtual nsReStyleHint
     HasAttributeDependentStyle(AttributeRuleProcessorData* aData);
   NS_IMETHOD MediumFeaturesChanged(nsPresContext* aPresContext,
                                    PRBool* aRulesChanged);
 
   // nsARefreshObserver
@@ -108,20 +103,19 @@ private:
                                   const nsTransition& aTransition,
                                   nsIContent *aElement,
                                   ElementTransitions *&aElementTransitions,
                                   nsStyleContext *aOldStyleContext,
                                   nsStyleContext *aNewStyleContext,
                                   PRBool *aStartedAny,
                                   nsCSSPropertySet *aWhichStarted);
   ElementTransitions* GetElementTransitions(nsIContent *aElement,
-                                            nsCSSPseudoElements::Type aPseudoType,
+                                            nsIAtom *aPseudo,
                                             PRBool aCreateIfNeeded);
   void AddElementTransitions(ElementTransitions* aElementTransitions);
   void TransitionsRemoved();
-  nsresult WalkTransitionRule(RuleProcessorData* aData,
-			      nsCSSPseudoElements::Type aPseudoType);
+  nsresult WalkTransitionRule(RuleProcessorData* aData, nsIAtom *aPseudo);
 
   PRCList mElementTransitions;
   nsPresContext *mPresContext;
 };
 
 #endif /* !defined(nsTransitionManager_h_) */
--- a/layout/style/test/Makefile.in
+++ b/layout/style/test/Makefile.in
@@ -167,17 +167,16 @@ GARBAGE += css_properties.js
 		xbl_bindings.xml \
 		empty.html \
 		media_queries_iframe.html \
 		media_queries_dynamic_xbl_binding.xml \
 		media_queries_dynamic_xbl_iframe.html \
 		media_queries_dynamic_xbl_style.css \
 		bug453896_iframe.html \
 		bug517224.sjs \
-		test_bug525952.html \
 		$(NULL)
 
 _BROWSER_FILES = \
 		browser_bug453896.js \
 		bug453896_iframe.html \
 		media_queries_iframe.html \
 		$(NULL)
 
deleted file mode 100644
--- a/layout/style/test/test_bug525952.html
+++ /dev/null
@@ -1,47 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=525952
--->
-<head>
-  <title>Test for Bug 525952</title>
-  <script type="application/javascript" src="/MochiKit/packed.js"></script>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=525952">Mozilla Bug 525952</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-  
-</div>
-<pre id="test">
-<script type="application/javascript">
-
-/** Test for Bug 525952 **/
-var bodies = document.querySelectorAll("::before, div::before, body");
-is(bodies.length, 1, "Unexpected length");
-is(bodies[0], document.body, "Unexpected element");
-
-is(document.querySelector("div > ::after, body"), document.body,
-   "Unexpected return value");
-
-var emptyList = document.querySelectorAll("::before, div::before");
-is(emptyList.length, 0, "Unexpected empty list length");
-
-is(document.querySelectorAll("div > ::after").length, 0,
-   "Pseudo-element matched something?");
-
-is(document.body.mozMatchesSelector("::first-line"), false,
-   "body shouldn't match ::first-line");
-
-is(document.body.mozMatchesSelector("::first-line, body"), true,
-   "body should match 'body'");
-
-is(document.body.mozMatchesSelector("::first-line, body, ::first-letter"), true,
-   "body should match 'body' here too");
-
-</script>
-</pre>
-</body>
-</html>
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -663,18 +663,19 @@ nsTableCellMap* nsTableFrame::GetCellMap
 nsTableColGroupFrame*
 nsTableFrame::CreateAnonymousColGroupFrame(nsTableColGroupType aColGroupType)
 {
   nsIContent* colGroupContent = GetContent();
   nsPresContext* presContext = PresContext();
   nsIPresShell *shell = presContext->PresShell();
 
   nsRefPtr<nsStyleContext> colGroupStyle;
-  colGroupStyle = shell->StyleSet()->
-    ResolveAnonymousBoxStyle(nsCSSAnonBoxes::tableColGroup, mStyleContext);
+  colGroupStyle = shell->StyleSet()->ResolvePseudoStyleFor(colGroupContent,
+                                                           nsCSSAnonBoxes::tableColGroup,
+                                                           mStyleContext);
   // Create a col group frame
   nsIFrame* newFrame = NS_NewTableColGroupFrame(shell, colGroupStyle);
   if (newFrame) {
     ((nsTableColGroupFrame *)newFrame)->SetColType(aColGroupType);
     newFrame->Init(colGroupContent, this, nsnull);
   }
   return (nsTableColGroupFrame *)newFrame;
 }
@@ -727,18 +728,19 @@ nsTableFrame::AppendAnonymousColFrames(n
     nsIContent* iContent;
     nsRefPtr<nsStyleContext> styleContext;
     nsStyleContext* parentStyleContext;
 
     // all anonymous cols that we create here use a pseudo style context of the
     // col group
     iContent = aColGroupFrame->GetContent();
     parentStyleContext = aColGroupFrame->GetStyleContext();
-    styleContext = shell->StyleSet()->
-      ResolveAnonymousBoxStyle(nsCSSAnonBoxes::tableCol, parentStyleContext);
+    styleContext = shell->StyleSet()->ResolvePseudoStyleFor(iContent,
+                                                            nsCSSAnonBoxes::tableCol,
+                                                            parentStyleContext);
     // ASSERTION to check for bug 54454 sneaking back in...
     NS_ASSERTION(iContent, "null content in CreateAnonymousColFrames");
 
     // create the new col frame
     nsIFrame* colFrame = NS_NewTableColFrame(shell, styleContext);
     ((nsTableColFrame *) colFrame)->SetColType(aColType);
     colFrame->Init(iContent, aColGroupFrame, nsnull);
 
--- a/layout/xul/base/src/tree/src/nsTreeStyleCache.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeStyleCache.cpp
@@ -96,18 +96,18 @@ nsTreeStyleCache::GetStyleContext(nsICSS
   // We're in a final state.
   // Look up our style context for this state.
   nsStyleContext* result = nsnull;
   if (mCache)
     result = static_cast<nsStyleContext*>(mCache->Get(currState));
   if (!result) {
     // We missed the cache. Resolve this pseudo-style.
     result = aPresContext->StyleSet()->
-      ResolveXULTreePseudoStyle(aContent, aPseudoElement,
-                                aContext, aComparator).get();
+      ResolvePseudoStyleFor(aContent, aPseudoElement,
+                            aContext, aComparator).get();
 
     // Put the style context in our table, transferring the owning reference to the table.
     if (!mCache) {
       mCache = new nsObjectHashtable(nsnull, nsnull, ReleaseStyleContext, nsnull);
       if (!mCache)
         return nsnull;
     }
     mCache->Put(currState, result);