Merge layout work from projects/birch, part 4. a=rs
authorL. David Baron <dbaron@dbaron.org>
Thu, 24 Mar 2011 14:36:14 -0700
changeset 63833 0798b52bb40d9c82368e3694d86db9bba7012e3e
parent 63823 bc7c390b2b435f7eed2e663290f80d8b9c7aa5dc (current diff)
parent 63832 497805f15c17a3bc9e19073bf90ec7ea9fe9bdb8 (diff)
child 63834 00f27b89cd7bf80061e9fd9714341593b3be0cb7
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrs
milestone2.2a1pre
first release with
nightly linux32
0798b52bb40d / 4.2a1pre / 20110324144535 / files
nightly mac
0798b52bb40d / 4.2a1pre / 20110324144210 / files
nightly win32
0798b52bb40d / 4.2a1pre / 20110324144234 / files
nightly linux64
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly mac
nightly win32
Merge layout work from projects/birch, part 4. a=rs
view/public/nsIView.h
view/src/nsView.cpp
view/src/nsView.h
--- a/accessible/tests/mochitest/tree/test_cssoverflow.html
+++ b/accessible/tests/mochitest/tree/test_cssoverflow.html
@@ -32,25 +32,29 @@
     {
       this.linkNode = getNode(aID);
       this.link = getAccessible(this.linkNode);
 
       this.eventSeq = [
         new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
       ];
 
+      this.unexpectedEventSeq = [
+        new invokerChecker(EVENT_REORDER, this.linkNode.parentNode)
+      ];
+
       this.invoke = function focusAnchor_invoke()
       {
         this.linkNode.focus();
       }
 
       this.check = function focusAnchor_check(aEvent)
       {
-        isnot(this.link, aEvent.accessible,
-              "Focus should be fired against new link accessible!");
+        is(this.link, aEvent.accessible,
+           "The link accessible shouldn't be recreated!");
       }
 
       this.getID = function focusAnchor_getID()
       {
         return "focus a:focus{overflow:scroll} #1";
       }
     }
 
@@ -58,25 +62,29 @@
     {
       this.linkNode = getNode(aID);
       this.link = getAccessible(this.linkNode);
 
       this.eventSeq = [
         new invokerChecker(EVENT_FOCUS, getAccessible, this.linkNode)
       ];
 
+      this.unexpectedEventSeq = [
+        new invokerChecker(EVENT_REORDER, this.linkNode.parentNode)
+      ];
+
       this.invoke = function tabAnchor_invoke()
       {
         synthesizeKey("VK_TAB", { shiftKey: false });
       }
 
       this.check = function tabAnchor_check(aEvent)
       {
-        isnot(this.link, aEvent.accessible,
-              "Focus should be fired against new link accessible!");
+        is(this.link, aEvent.accessible,
+           "The link accessible shouldn't be recreated!");
       }
 
       this.getID = function tabAnchor_getID()
       {
         return "focus a:focus{overflow:scroll} #2";
       }
     }
 
@@ -114,16 +122,21 @@
      title="mochitest for bug 413777: focus the a:focus {overflow: scroll;} shouldn't recreate HTML a accessible">
     Mozilla Bug 591163
   </a><br>
   <a target="_blank"
      title="Rework accessible tree update code"
      href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
     Mozilla Bug 570275
   </a><br>
+  <a target="_blank"
+     title="Don't recreate frames for inlines with overflow style applied"
+     href="https://bugzilla.mozilla.org/show_bug.cgi?id=606087">
+    Mozilla Bug 606087
+  </a><br>
 
   <p id="display"></p>
   <div id="content" style="display: none"></div>
   <pre id="test">
   </pre>
   <div id="eventdump"></div>
 
   <div>
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -3211,29 +3211,16 @@ nsCSSFrameConstructor::InitializeSelectF
     nsresult rv = aState.AddChild(scrollFrame, aFrameItems, aContent,
                                   aStyleContext, aParentFrame);
     if (NS_FAILED(rv)) {
       return rv;
     }
   }
       
   nsHTMLContainerFrame::CreateViewForFrame(scrollFrame, aBuildCombobox);
-  if (aBuildCombobox) {
-    // Give the drop-down list a popup widget
-    nsIView* view = scrollFrame->GetView();
-    NS_ASSERTION(view, "We asked for a view but didn't get one");
-    if (view) {
-      view->GetViewManager()->SetViewFloating(view, PR_TRUE);
-
-      nsWidgetInitData widgetData;
-      widgetData.mWindowType  = eWindowType_popup;
-      widgetData.mBorderStyle = eBorderStyle_default;
-      view->CreateWidgetForPopup(&widgetData);
-    }
-  }
 
   BuildScrollFrame(aState, aContent, aStyleContext, scrolledFrame,
                    geometricParent, scrollFrame);
 
   if (aState.mFrameState && aState.mFrameManager) {
     // Restore frame state for the scroll frame
     aState.mFrameManager->RestoreFrameStateFor(scrollFrame, aState.mFrameState);
   }
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -382,16 +382,31 @@ nsComboboxControlFrame::ShowPopup(PRBool
 }
 
 PRBool
 nsComboboxControlFrame::ShowList(PRBool aShowList)
 {
   nsCOMPtr<nsIPresShell> shell = PresContext()->GetPresShell();
 
   nsWeakFrame weakFrame(this);
+
+  if (aShowList) {
+    nsIView* view = mDropdownFrame->GetView();
+    NS_ASSERTION(!view->HasWidget(),
+                 "We shoudldn't have a widget before we need to display the popup");
+
+    // Create the widget for the drop-down list
+    view->GetViewManager()->SetViewFloating(view, PR_TRUE);
+
+    nsWidgetInitData widgetData;
+    widgetData.mWindowType  = eWindowType_popup;
+    widgetData.mBorderStyle = eBorderStyle_default;
+    view->CreateWidgetForPopup(&widgetData);
+  }
+
   ShowPopup(aShowList);  // might destroy us
   if (!weakFrame.IsAlive()) {
     return PR_FALSE;
   }
 
   mDroppedDown = aShowList;
   if (mDroppedDown) {
     // The listcontrol frame will call back to the nsComboboxControlFrame's
@@ -407,18 +422,23 @@ nsComboboxControlFrame::ShowList(PRBool 
   }
 
   nsIFrame* listFrame = do_QueryFrame(mListControlFrame);
   if (listFrame) {
     nsIView* view = listFrame->GetView();
     NS_ASSERTION(view, "nsComboboxControlFrame view is null");
     if (view) {
       nsIWidget* widget = view->GetWidget();
-      if (widget)
+      if (widget) {
         widget->CaptureRollupEvents(this, nsnull, mDroppedDown, mDroppedDown);
+
+        if (!aShowList) {
+          view->DestroyWidget();
+        }
+      }
     }
   }
 
   return weakFrame.IsAlive();
 }
 
 nsresult
 nsComboboxControlFrame::ReflowDropdown(nsPresContext*  aPresContext, 
--- a/layout/style/StyleRule.cpp
+++ b/layout/style/StyleRule.cpp
@@ -129,101 +129,93 @@ 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)
-  : mAtom(aAtom),
-    mType(aType),
+nsPseudoClassList::nsPseudoClassList(nsCSSPseudoClasses::Type aType)
+  : mType(aType),
     mNext(nsnull)
 {
-  NS_ASSERTION(!nsCSSPseudoClasses::HasStringArg(aAtom) &&
-               !nsCSSPseudoClasses::HasNthPairArg(aAtom),
+  NS_ASSERTION(!nsCSSPseudoClasses::HasStringArg(aType) &&
+               !nsCSSPseudoClasses::HasNthPairArg(aType),
                "unexpected pseudo-class");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mMemory = nsnull;
 }
 
-nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom,
-                                     nsCSSPseudoClasses::Type aType,
+nsPseudoClassList::nsPseudoClassList(nsCSSPseudoClasses::Type aType,
                                      const PRUnichar* aString)
-  : mAtom(aAtom),
-    mType(aType),
+  : mType(aType),
     mNext(nsnull)
 {
-  NS_ASSERTION(nsCSSPseudoClasses::HasStringArg(aAtom),
+  NS_ASSERTION(nsCSSPseudoClasses::HasStringArg(aType),
                "unexpected pseudo-class");
   NS_ASSERTION(aString, "string expected");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mString = NS_strdup(aString);
 }
 
-nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom,
-                                     nsCSSPseudoClasses::Type aType,
+nsPseudoClassList::nsPseudoClassList(nsCSSPseudoClasses::Type aType,
                                      const PRInt32* aIntPair)
-  : mAtom(aAtom),
-    mType(aType),
+  : mType(aType),
     mNext(nsnull)
 {
-  NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(aAtom),
+  NS_ASSERTION(nsCSSPseudoClasses::HasNthPairArg(aType),
                "unexpected pseudo-class");
   NS_ASSERTION(aIntPair, "integer pair expected");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mNumbers =
     static_cast<PRInt32*>(nsMemory::Clone(aIntPair, sizeof(PRInt32) * 2));
 }
 
 // adopts aSelectorList
-nsPseudoClassList::nsPseudoClassList(nsIAtom* aAtom,
-                                     nsCSSPseudoClasses::Type aType,
+nsPseudoClassList::nsPseudoClassList(nsCSSPseudoClasses::Type aType,
                                      nsCSSSelectorList* aSelectorList)
-  : mAtom(aAtom),
-    mType(aType),
+  : mType(aType),
     mNext(nsnull)
 {
-  NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(aAtom),
+  NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(aType),
                "unexpected pseudo-class");
   NS_ASSERTION(aSelectorList, "selector list expected");
   MOZ_COUNT_CTOR(nsPseudoClassList);
   u.mSelectors = aSelectorList;
 }
 
 nsPseudoClassList*
 nsPseudoClassList::Clone(PRBool aDeep) const
 {
   nsPseudoClassList *result;
   if (!u.mMemory) {
-    result = new nsPseudoClassList(mAtom, mType);
-  } else if (nsCSSPseudoClasses::HasStringArg(mAtom)) {
-    result = new nsPseudoClassList(mAtom, mType, u.mString);
-  } else if (nsCSSPseudoClasses::HasNthPairArg(mAtom)) {
-    result = new nsPseudoClassList(mAtom, mType, u.mNumbers);
+    result = new nsPseudoClassList(mType);
+  } else if (nsCSSPseudoClasses::HasStringArg(mType)) {
+    result = new nsPseudoClassList(mType, u.mString);
+  } else if (nsCSSPseudoClasses::HasNthPairArg(mType)) {
+    result = new nsPseudoClassList(mType, u.mNumbers);
   } else {
-    NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(mAtom),
+    NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(mType),
                  "unexpected pseudo-class");
     // This constructor adopts its selector list argument.
-    result = new nsPseudoClassList(mAtom, mType, u.mSelectors->Clone());
+    result = new nsPseudoClassList(mType, u.mSelectors->Clone());
   }
 
   if (aDeep)
     NS_CSS_CLONE_LIST_MEMBER(nsPseudoClassList, this, mNext, result,
                              (PR_FALSE));
 
   return result;
 }
 
 nsPseudoClassList::~nsPseudoClassList(void)
 {
   MOZ_COUNT_DTOR(nsPseudoClassList);
-  if (nsCSSPseudoClasses::HasSelectorListArg(mAtom)) {
+  if (nsCSSPseudoClasses::HasSelectorListArg(mType)) {
     delete u.mSelectors;
   } else if (u.mMemory) {
     NS_Free(u.mMemory);
   }
   NS_CSS_DELETE_LIST_MEMBER(nsPseudoClassList, this, mNext);
 }
 
 nsAttrSelector::nsAttrSelector(PRInt32 aNameSpace, const nsString& aAttr)
@@ -414,43 +406,38 @@ 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(nsCSSPseudoClasses::Type aType)
 {
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType));
+  AddPseudoClassInternal(new nsPseudoClassList(aType));
 }
 
-void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
-                                   nsCSSPseudoClasses::Type aType,
+void nsCSSSelector::AddPseudoClass(nsCSSPseudoClasses::Type aType,
                                    const PRUnichar* aString)
 {
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType, aString));
+  AddPseudoClassInternal(new nsPseudoClassList(aType, aString));
 }
 
-void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
-                                   nsCSSPseudoClasses::Type aType,
+void nsCSSSelector::AddPseudoClass(nsCSSPseudoClasses::Type aType,
                                    const PRInt32* aIntPair)
 {
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType, aIntPair));
+  AddPseudoClassInternal(new nsPseudoClassList(aType, aIntPair));
 }
 
-void nsCSSSelector::AddPseudoClass(nsIAtom* aPseudoClass,
-                                   nsCSSPseudoClasses::Type aType,
+void nsCSSSelector::AddPseudoClass(nsCSSPseudoClasses::Type aType,
                                    nsCSSSelectorList* aSelectorList)
 {
   // Take ownership of nsCSSSelectorList instead of copying.
-  AddPseudoClassInternal(new nsPseudoClassList(aPseudoClass, aType,
-                                               aSelectorList));
+  AddPseudoClassInternal(new nsPseudoClassList(aType, aSelectorList));
 }
 
 void nsCSSSelector::AddPseudoClassInternal(nsPseudoClassList *aPseudoClass)
 {
   nsPseudoClassList** list = &mPseudoClassList;
   while (nsnull != *list) {
     list = &((*list)->mNext);
   }
@@ -692,22 +679,39 @@ nsCSSSelector::AppendToStringWithoutComb
       aString.Append(PRUnichar('#'));
       nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
       list = list->mNext;
     }
   }
 
   // Append each class in the linked list
   if (mClassList) {
-    nsAtomList* list = mClassList;
-    while (list != nsnull) {
-      list->mAtom->ToString(temp);
-      aString.Append(PRUnichar('.'));
-      nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
-      list = list->mNext;
+    if (isPseudoElement) {
+#ifdef MOZ_XUL
+      NS_ABORT_IF_FALSE(nsCSSAnonBoxes::IsTreePseudoElement(mLowercaseTag),
+                        "must be tree pseudo-element");
+
+      aString.Append(PRUnichar('('));
+      for (nsAtomList* list = mClassList; list; list = list->mNext) {
+        nsStyleUtil::AppendEscapedCSSIdent(nsDependentAtomString(list->mAtom), aString);
+        aString.Append(PRUnichar(','));
+      }
+      // replace the final comma with a close-paren
+      aString.Replace(aString.Length() - 1, 1, PRUnichar(')'));
+#else
+      NS_ERROR("Can't happen");
+#endif
+    } else {
+      nsAtomList* list = mClassList;
+      while (list != nsnull) {
+        list->mAtom->ToString(temp);
+        aString.Append(PRUnichar('.'));
+        nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
+        list = list->mNext;
+      }
     }
   }
 
   // Append each attribute selector in the linked list
   if (mAttrList) {
     nsAttrSelector* list = mAttrList;
     while (list != nsnull) {
       aString.Append(PRUnichar('['));
@@ -755,75 +759,54 @@ nsCSSSelector::AppendToStringWithoutComb
 
       aString.Append(PRUnichar(']'));
       
       list = list->mNext;
     }
   }
 
   // Append each pseudo-class in the linked list
-  if (isPseudoElement) {
-#ifdef MOZ_XUL
-    if (mPseudoClassList) {
-      NS_ABORT_IF_FALSE(nsCSSAnonBoxes::IsTreePseudoElement(mLowercaseTag),
-                        "must be tree pseudo-element");
+  for (nsPseudoClassList* list = mPseudoClassList; list; list = list->mNext) {
+    nsCSSPseudoClasses::PseudoTypeToString(list->mType, temp);
+    // This should not be escaped since (a) the pseudo-class string
+    // has a ":" that can't be escaped and (b) all pseudo-classes at
+    // this point are known, and therefore we know they don't need
+    // escaping.
+    aString.Append(temp);
+    if (list->u.mMemory) {
       aString.Append(PRUnichar('('));
-      for (nsPseudoClassList* list = mPseudoClassList; list;
-           list = list->mNext) {
-        list->mAtom->ToString(temp);
-        nsStyleUtil::AppendEscapedCSSIdent(temp, aString);
-        NS_ABORT_IF_FALSE(!list->u.mMemory, "data not expected");
-        aString.Append(PRUnichar(','));
+      if (nsCSSPseudoClasses::HasStringArg(list->mType)) {
+        nsStyleUtil::AppendEscapedCSSIdent(
+          nsDependentString(list->u.mString), aString);
+      } else if (nsCSSPseudoClasses::HasNthPairArg(list->mType)) {
+        PRInt32 a = list->u.mNumbers[0],
+                b = list->u.mNumbers[1];
+        temp.Truncate();
+        if (a != 0) {
+          if (a == -1) {
+            temp.Append(PRUnichar('-'));
+          } else if (a != 1) {
+            temp.AppendInt(a);
+          }
+          temp.Append(PRUnichar('n'));
+        }
+        if (b != 0 || a == 0) {
+          if (b >= 0 && a != 0) // check a != 0 for whether we printed above
+            temp.Append(PRUnichar('+'));
+          temp.AppendInt(b);
+        }
+        aString.Append(temp);
+      } else {
+        NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(list->mType),
+                     "unexpected pseudo-class");
+        nsString tmp;
+        list->u.mSelectors->ToString(tmp, aSheet);
+        aString.Append(tmp);
       }
-      // replace the final comma with a close-paren
-      aString.Replace(aString.Length() - 1, 1, PRUnichar(')'));
-    }
-#else
-    NS_ABORT_IF_FALSE(!mPseudoClassList, "unexpected pseudo-class list");
-#endif
-  } else {
-    for (nsPseudoClassList* list = mPseudoClassList; list; list = list->mNext) {
-      list->mAtom->ToString(temp);
-      // This should not be escaped since (a) the pseudo-class string
-      // has a ":" that can't be escaped and (b) all pseudo-classes at
-      // this point are known, and therefore we know they don't need
-      // escaping.
-      aString.Append(temp);
-      if (list->u.mMemory) {
-        aString.Append(PRUnichar('('));
-        if (nsCSSPseudoClasses::HasStringArg(list->mAtom)) {
-          nsStyleUtil::AppendEscapedCSSIdent(
-            nsDependentString(list->u.mString), aString);
-        } else if (nsCSSPseudoClasses::HasNthPairArg(list->mAtom)) {
-          PRInt32 a = list->u.mNumbers[0],
-                  b = list->u.mNumbers[1];
-          temp.Truncate();
-          if (a != 0) {
-            if (a == -1) {
-              temp.Append(PRUnichar('-'));
-            } else if (a != 1) {
-              temp.AppendInt(a);
-            }
-            temp.Append(PRUnichar('n'));
-          }
-          if (b != 0 || a == 0) {
-            if (b >= 0 && a != 0) // check a != 0 for whether we printed above
-              temp.Append(PRUnichar('+'));
-            temp.AppendInt(b);
-          }
-          aString.Append(temp);
-        } else {
-          NS_ASSERTION(nsCSSPseudoClasses::HasSelectorListArg(list->mAtom),
-                       "unexpected pseudo-class");
-          nsString tmp;
-          list->u.mSelectors->ToString(tmp, aSheet);
-          aString.Append(tmp);
-        }
-        aString.Append(PRUnichar(')'));
-      }
+      aString.Append(PRUnichar(')'));
     }
   }
 }
 
 PRBool
 nsCSSSelector::CanBeNamespaced(PRBool aIsNegated) const
 {
   return !aIsNegated ||
--- a/layout/style/StyleRule.h
+++ b/layout/style/StyleRule.h
@@ -75,39 +75,36 @@ 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, nsCSSPseudoClasses::Type aType,
+  nsPseudoClassList(nsCSSPseudoClasses::Type aType);
+  nsPseudoClassList(nsCSSPseudoClasses::Type aType, const PRUnichar *aString);
+  nsPseudoClassList(nsCSSPseudoClasses::Type aType, const PRInt32 *aIntPair);
+  nsPseudoClassList(nsCSSPseudoClasses::Type aType,
                     nsCSSSelectorList *aSelectorList /* takes ownership */);
   ~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:
+    // For a given value of mType, we have either:
     //   a. no value, which means mMemory is always null
     //      (if none of the conditions for (b), (c), or (d) is true)
     //   b. a string value, which means mString/mMemory is non-null
-    //      (if nsCSSPseudoClasses::HasStringArg(mAtom))
+    //      (if nsCSSPseudoClasses::HasStringArg(mType))
     //   c. an integer pair value, which means mNumbers/mMemory is non-null
-    //      (if nsCSSPseudoClasses::HasNthPairArg(mAtom))
+    //      (if nsCSSPseudoClasses::HasNthPairArg(mType))
     //   d. a selector list, which means mSelectors is non-null
-    //      (if nsCSSPseudoClasses::HasSelectorListArg(mAtom))
+    //      (if nsCSSPseudoClasses::HasSelectorListArg(mType))
     void*           mMemory; // mString and mNumbers use NS_Alloc/NS_Free
     PRUnichar*      mString;
     PRInt32*        mNumbers;
     nsCSSSelectorList* mSelectors;
   } u;
   nsCSSPseudoClasses::Type mType;
   nsPseudoClassList* mNext;
 private: 
@@ -163,23 +160,21 @@ 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(nsCSSPseudoClasses::Type aType);
+  void AddPseudoClass(nsCSSPseudoClasses::Type aType, const PRUnichar* aString);
+  void AddPseudoClass(nsCSSPseudoClasses::Type aType, const PRInt32* aIntPair);
   // takes ownership of aSelectorList
-  void AddPseudoClass(nsIAtom* aPseudoClass, nsCSSPseudoClasses::Type aType,
+  void AddPseudoClass(nsCSSPseudoClasses::Type aType,
                       nsCSSSelectorList* aSelectorList);
   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;
--- a/layout/style/nsCSSParser.cpp
+++ b/layout/style/nsCSSParser.cpp
@@ -377,36 +377,33 @@ 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,
+                                              nsAtomList**   aPseudoElementArgs,
                                               nsCSSPseudoElements::Type* aPseudoElementType);
 
   nsSelectorParsingStatus ParseAttributeSelector(PRInt32&       aDataMask,
                                                  nsCSSSelector& aSelector);
 
   nsSelectorParsingStatus ParseTypeOrUniversalSelector(PRInt32&       aDataMask,
                                                        nsCSSSelector& aSelector,
                                                        PRBool         aIsNegated);
 
   nsSelectorParsingStatus ParsePseudoClassWithIdentArg(nsCSSSelector& aSelector,
-                                                       nsIAtom*       aPseudo,
                                                        nsCSSPseudoClasses::Type aType);
 
   nsSelectorParsingStatus ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
-                                                         nsIAtom*       aPseudo,
                                                          nsCSSPseudoClasses::Type aType);
 
   nsSelectorParsingStatus ParsePseudoClassWithSelectorListArg(nsCSSSelector& aSelector,
-                                                              nsIAtom*       aPseudo,
                                                               nsCSSPseudoClasses::Type aType);
 
   nsSelectorParsingStatus ParseNegatedSimpleSelector(PRInt32&       aDataMask,
                                                      nsCSSSelector& aSelector);
 
   // If aStopChar is non-zero, the selector list is done when we hit
   // aStopChar.  Otherwise, it's done when we hit EOF.
   PRBool ParseSelectorList(nsCSSSelectorList*& aListHead,
@@ -428,17 +425,17 @@ protected:
   enum PriorityParsingStatus {
     ePriority_None,
     ePriority_Important,
     ePriority_Error
   };
   PriorityParsingStatus ParsePriority();
 
 #ifdef MOZ_XUL
-  PRBool ParseTreePseudoElement(nsPseudoClassList **aPseudoElementArgs);
+  PRBool ParseTreePseudoElement(nsAtomList **aPseudoElementArgs);
 #endif
 
   void InitBoxPropsAsPhysical(const nsCSSProperty *aSourceProperties);
 
   // Property specific parsing routines
   PRBool ParseAzimuth(nsCSSValue& aValue);
   PRBool ParseBackground();
 
@@ -2957,17 +2954,17 @@ CSSParserImpl::ParseAttributeSelector(PR
 //
 // Parse pseudo-classes and pseudo-elements
 //
 CSSParserImpl::nsSelectorParsingStatus
 CSSParserImpl::ParsePseudoSelector(PRInt32&       aDataMask,
                                    nsCSSSelector& aSelector,
                                    PRBool         aIsNegated,
                                    nsIAtom**      aPseudoElement,
-                                   nsPseudoClassList** aPseudoElementArgs,
+                                   nsAtomList**   aPseudoElementArgs,
                                    nsCSSPseudoElements::Type* aPseudoElementType)
 {
   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
@@ -3047,75 +3044,76 @@ CSSParserImpl::ParsePseudoSelector(PRInt
 
   // If it's a function token, it better be on our "ok" list, and if the name
   // is that of a function pseudo it better be a function token
   if ((eCSSToken_Function == mToken.mType) !=
       (
 #ifdef MOZ_XUL
        isTree ||
 #endif
-       nsCSSPseudoClasses::notPseudo == pseudo ||
-       nsCSSPseudoClasses::HasStringArg(pseudo) ||
-       nsCSSPseudoClasses::HasNthPairArg(pseudo) ||
-       nsCSSPseudoClasses::HasSelectorListArg(pseudo))) {
+       nsCSSPseudoClasses::ePseudoClass_notPseudo == pseudoClassType ||
+       nsCSSPseudoClasses::HasStringArg(pseudoClassType) ||
+       nsCSSPseudoClasses::HasNthPairArg(pseudoClassType) ||
+       nsCSSPseudoClasses::HasSelectorListArg(pseudoClassType))) {
     // There are no other function pseudos
     REPORT_UNEXPECTED_TOKEN(PEPseudoSelNonFunc);
     UngetToken();
     return eSelectorParsingStatus_Error;
   }
 
   // If it starts with "::", it better be a pseudo-element
   if (parsingPseudoElement &&
       !isPseudoElement &&
       !isAnonBox) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoSelNotPE);
     UngetToken();
     return eSelectorParsingStatus_Error;
   }
 
-  if (!parsingPseudoElement && nsCSSPseudoClasses::notPseudo == pseudo) {
+  if (!parsingPseudoElement &&
+      nsCSSPseudoClasses::ePseudoClass_notPseudo == pseudoClassType) {
     if (aIsNegated) { // :not() can't be itself negated
       REPORT_UNEXPECTED_TOKEN(PEPseudoSelDoubleNot);
       UngetToken();
       return eSelectorParsingStatus_Error;
     }
     // CSS 3 Negation pseudo-class takes one simple selector as argument
     nsSelectorParsingStatus parsingStatus =
       ParseNegatedSimpleSelector(aDataMask, aSelector);
     if (eSelectorParsingStatus_Continue != parsingStatus) {
       return parsingStatus;
     }
   }
   else if (!parsingPseudoElement && isPseudoClass) {
     aDataMask |= SEL_MASK_PCLASS;
     if (eCSSToken_Function == mToken.mType) {
       nsSelectorParsingStatus parsingStatus;
-      if (nsCSSPseudoClasses::HasStringArg(pseudo)) {
+      if (nsCSSPseudoClasses::HasStringArg(pseudoClassType)) {
         parsingStatus =
-          ParsePseudoClassWithIdentArg(aSelector, pseudo, pseudoClassType);
-      }
-      else if (nsCSSPseudoClasses::HasNthPairArg(pseudo)) {
+          ParsePseudoClassWithIdentArg(aSelector, pseudoClassType);
+      }
+      else if (nsCSSPseudoClasses::HasNthPairArg(pseudoClassType)) {
         parsingStatus =
-          ParsePseudoClassWithNthPairArg(aSelector, pseudo, pseudoClassType);
+          ParsePseudoClassWithNthPairArg(aSelector, pseudoClassType);
       }
       else {
-        NS_ABORT_IF_FALSE(nsCSSPseudoClasses::HasSelectorListArg(pseudo),
+        NS_ABORT_IF_FALSE(nsCSSPseudoClasses::HasSelectorListArg(pseudoClassType),
                           "unexpected pseudo with function token");
-        parsingStatus = ParsePseudoClassWithSelectorListArg(aSelector, pseudo,
+        parsingStatus = ParsePseudoClassWithSelectorListArg(aSelector,
                                                             pseudoClassType);
       }
       if (eSelectorParsingStatus_Continue != parsingStatus) {
         if (eSelectorParsingStatus_Error == parsingStatus) {
           SkipUntil(')');
         }
         return parsingStatus;
       }
     }
     else {
-      aSelector.AddPseudoClass(pseudo, pseudoClassType);
+      aSelector.AddPseudoClass(pseudoClassType);
     }
   }
   else if (isPseudoElement || isAnonBox) {
     // Pseudo-element.  Make some more sanity checks.
 
     if (aIsNegated) { // pseudo-elements can't be negated
       REPORT_UNEXPECTED_TOKEN(PEPseudoSelPEInNot);
       UngetToken();
@@ -3263,53 +3261,51 @@ 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)
 {
   if (! GetToken(PR_TRUE)) { // premature eof
     REPORT_UNEXPECTED_EOF(PEPseudoClassArgEOF);
     return eSelectorParsingStatus_Error;
   }
   // We expect an identifier with a language abbreviation
   if (eCSSToken_Ident != mToken.mType) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassArgNotIdent);
     UngetToken();
     return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
   }
 
   // -moz-locale-dir can only have values of 'ltr' or 'rtl'.
-  if (aPseudo == nsCSSPseudoClasses::mozLocaleDir) {
+  if (aType == nsCSSPseudoClasses::ePseudoClass_mozLocaleDir) {
     if (!mToken.mIdent.EqualsLiteral("ltr") &&
         !mToken.mIdent.EqualsLiteral("rtl")) {
       return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
     }
   }
 
   // Add the pseudo with the language parameter
-  aSelector.AddPseudoClass(aPseudo, aType, mToken.mIdent.get());
+  aSelector.AddPseudoClass(aType, mToken.mIdent.get());
 
   // close the parenthesis
   if (!ExpectSymbol(')', PR_TRUE)) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoClose);
     return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
   }
 
   return eSelectorParsingStatus_Continue;
 }
 
 CSSParserImpl::nsSelectorParsingStatus
 CSSParserImpl::ParsePseudoClassWithNthPairArg(nsCSSSelector& aSelector,
-                                              nsIAtom*       aPseudo,
                                               nsCSSPseudoClasses::Type aType)
 {
   PRInt32 numbers[2] = { 0, 0 };
   PRBool lookForB = PR_TRUE;
 
   // Follow the whitespace rules as proposed in
   // http://lists.w3.org/Archives/Public/www-style/2008Mar/0121.html
 
@@ -3412,28 +3408,27 @@ CSSParserImpl::ParsePseudoClassWithNthPa
       REPORT_UNEXPECTED_EOF(PEPseudoClassArgEOF);
       return eSelectorParsingStatus_Error;
     }
   }
   if (!mToken.IsSymbol(')')) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoClose);
     return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
   }
-  aSelector.AddPseudoClass(aPseudo, aType, numbers);
+  aSelector.AddPseudoClass(aType, numbers);
   return eSelectorParsingStatus_Continue;
 }
 
 //
 // Parse the argument of a pseudo-class that has a selector list argument.
 // Such selector lists cannot contain combinators, but can contain
 // anything that goes between a pair of combinators.
 //
 CSSParserImpl::nsSelectorParsingStatus
 CSSParserImpl::ParsePseudoClassWithSelectorListArg(nsCSSSelector& aSelector,
-                                                   nsIAtom*       aPseudo,
                                                    nsCSSPseudoClasses::Type aType)
 {
   nsAutoPtr<nsCSSSelectorList> slist;
   if (! ParseSelectorList(*getter_Transfers(slist), PRUnichar(')'))) {
     return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
   }
 
   // Check that none of the selectors in the list have combinators or
@@ -3441,17 +3436,17 @@ CSSParserImpl::ParsePseudoClassWithSelec
   for (nsCSSSelectorList *l = slist; l; l = l->mNext) {
     nsCSSSelector *s = l->mSelectors;
     if (s->mNext || s->IsPseudoElement()) {
       return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
     }
   }
 
   // Add the pseudo with the selector list parameter
-  aSelector.AddPseudoClass(aPseudo, aType, slist.forget());
+  aSelector.AddPseudoClass(aType, slist.forget());
 
   // close the parenthesis
   if (!ExpectSymbol(')', PR_TRUE)) {
     REPORT_UNEXPECTED_TOKEN(PEPseudoClassNoClose);
     return eSelectorParsingStatus_Error; // our caller calls SkipUntil(')')
   }
 
   return eSelectorParsingStatus_Continue;
@@ -3468,17 +3463,17 @@ CSSParserImpl::ParseSelector(nsCSSSelect
 {
   if (! GetToken(PR_TRUE)) {
     REPORT_UNEXPECTED_EOF(PESelectorEOF);
     return PR_FALSE;
   }
 
   nsCSSSelector* selector = aList->AddSelector(aPrevCombinator);
   nsCOMPtr<nsIAtom> pseudoElement;
-  nsAutoPtr<nsPseudoClassList> pseudoElementArgs;
+  nsAutoPtr<nsAtomList> pseudoElementArgs;
   nsCSSPseudoElements::Type pseudoElementType =
     nsCSSPseudoElements::ePseudo_NotPseudoElement;
 
   PRInt32 dataMask = 0;
   nsSelectorParsingStatus parsingStatus =
     ParseTypeOrUniversalSelector(dataMask, *selector, PR_FALSE);
 
   while (parsingStatus == eSelectorParsingStatus_Continue) {
@@ -3535,30 +3530,30 @@ CSSParserImpl::ParseSelector(nsCSSSelect
     if (selector->mNext || !IsUniversalSelector(*selector)) {
       REPORT_UNEXPECTED(PEAnonBoxNotAlone);
       return PR_FALSE;
     }
 
     // Rewrite the current selector as this pseudo-element.
     // It does not contribute to selector weight.
     selector->mLowercaseTag.swap(pseudoElement);
-    selector->mPseudoClassList = pseudoElementArgs.forget();
+    selector->mClassList = pseudoElementArgs.forget();
     selector->SetPseudoType(pseudoElementType);
     return PR_TRUE;
   }
 
   aList->mWeight += selector->CalcWeight();
 
   // Pseudo-elements other than anonymous boxes are represented as
   // direct children ('>' combinator) of the rest of the selector.
   if (pseudoElement) {
     selector = aList->AddSelector('>');
 
     selector->mLowercaseTag.swap(pseudoElement);
-    selector->mPseudoClassList = pseudoElementArgs.forget();
+    selector->mClassList = pseudoElementArgs.forget();
     selector->SetPseudoType(pseudoElementType);
   }
 
   return PR_TRUE;
 }
 
 css::Declaration*
 CSSParserImpl::ParseDeclarationBlock(PRBool aCheckForBraces)
@@ -3930,40 +3925,38 @@ CSSParserImpl::ParseColorOpacity(PRUint8
 
   aOpacity = value;
 
   return PR_TRUE;
 }
 
 #ifdef MOZ_XUL
 PRBool
-CSSParserImpl::ParseTreePseudoElement(nsPseudoClassList **aPseudoElementArgs)
+CSSParserImpl::ParseTreePseudoElement(nsAtomList **aPseudoElementArgs)
 {
   // The argument to a tree pseudo-element is a sequence of identifiers
   // that are either space- or comma-separated.  (Was the intent to
   // allow only comma-separated?  That's not what was done.)
   nsCSSSelector fakeSelector; // so we can reuse AddPseudoClass
 
   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.AddClass(mToken.mIdent);
     }
     else if (!mToken.IsSymbol(',')) {
       UngetToken();
       SkipUntil(')');
       return PR_FALSE;
     }
   }
-  *aPseudoElementArgs = fakeSelector.mPseudoClassList;
-  fakeSelector.mPseudoClassList = nsnull;
+  *aPseudoElementArgs = fakeSelector.mClassList;
+  fakeSelector.mClassList = nsnull;
   return PR_TRUE;
 }
 #endif
 
 //----------------------------------------------------------------------
 
 PRBool
 CSSParserImpl::ParseDeclaration(css::Declaration* aDeclaration,
--- a/layout/style/nsCSSPseudoClasses.cpp
+++ b/layout/style/nsCSSPseudoClasses.cpp
@@ -39,61 +39,62 @@
 /* atom list for CSS pseudo-classes */
 
 #include "nsCSSPseudoClasses.h"
 #include "nsAtomListUtils.h"
 #include "nsStaticAtom.h"
 #include "nsMemory.h"
 
 // define storage for all atoms
-#define CSS_PSEUDO_CLASS(_name, _value) \
-  nsICSSPseudoClass* nsCSSPseudoClasses::_name;
+#define CSS_PSEUDO_CLASS(_name, _value) static nsIAtom* sPseudoClass_##_name;
 #include "nsCSSPseudoClassList.h"
 #undef CSS_PSEUDO_CLASS
 
 #define CSS_PSEUDO_CLASS(name_, value_) \
   NS_STATIC_ATOM_BUFFER(name_##_buffer, value_)
 #include "nsCSSPseudoClassList.h"
 #undef CSS_PSEUDO_CLASS
 
 static const nsStaticAtom CSSPseudoClasses_info[] = {
 #define CSS_PSEUDO_CLASS(name_, value_) \
-  NS_STATIC_ATOM(name_##_buffer, (nsIAtom**)&nsCSSPseudoClasses::name_),
+  NS_STATIC_ATOM(name_##_buffer, &sPseudoClass_##name_),
 #include "nsCSSPseudoClassList.h"
 #undef CSS_PSEUDO_CLASS
 };
 
 void nsCSSPseudoClasses::AddRefAtoms()
 {
   NS_RegisterStaticAtoms(CSSPseudoClasses_info,
                          NS_ARRAY_LENGTH(CSSPseudoClasses_info));
 }
 
 PRBool
-nsCSSPseudoClasses::HasStringArg(nsIAtom* aAtom)
+nsCSSPseudoClasses::HasStringArg(Type aType)
 {
-  return aAtom == nsCSSPseudoClasses::lang ||
-         aAtom == nsCSSPseudoClasses::mozEmptyExceptChildrenWithLocalname ||
-         aAtom == nsCSSPseudoClasses::mozSystemMetric ||
-         aAtom == nsCSSPseudoClasses::mozLocaleDir;
+  return aType == ePseudoClass_lang ||
+         aType == ePseudoClass_mozEmptyExceptChildrenWithLocalname ||
+         aType == ePseudoClass_mozSystemMetric ||
+         aType == ePseudoClass_mozLocaleDir;
 }
 
 PRBool
-nsCSSPseudoClasses::HasNthPairArg(nsIAtom* aAtom)
+nsCSSPseudoClasses::HasNthPairArg(Type aType)
 {
-  return aAtom == nsCSSPseudoClasses::nthChild ||
-         aAtom == nsCSSPseudoClasses::nthLastChild ||
-         aAtom == nsCSSPseudoClasses::nthOfType ||
-         aAtom == nsCSSPseudoClasses::nthLastOfType;
+  return aType == ePseudoClass_nthChild ||
+         aType == ePseudoClass_nthLastChild ||
+         aType == ePseudoClass_nthOfType ||
+         aType == ePseudoClass_nthLastOfType;
 }
 
-PRBool
-nsCSSPseudoClasses::HasSelectorListArg(nsIAtom* aAtom)
+void
+nsCSSPseudoClasses::PseudoTypeToString(Type aType, nsAString& aString)
 {
-  return aAtom == nsCSSPseudoClasses::any;
+  NS_ABORT_IF_FALSE(aType < ePseudoClass_Count, "Unexpected type");
+  NS_ABORT_IF_FALSE(aType >= 0, "Very unexpected type");
+  (*CSSPseudoClasses_info[aType].mAtom)->ToString(aString);
 }
 
 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);
--- a/layout/style/nsCSSPseudoClasses.h
+++ b/layout/style/nsCSSPseudoClasses.h
@@ -38,39 +38,35 @@
 
 /* atom list for CSS pseudo-classes */
 
 #ifndef nsCSSPseudoClasses_h___
 #define nsCSSPseudoClasses_h___
 
 #include "nsIAtom.h"
 
-// Empty class derived from nsIAtom so that function signatures can
-// require an atom from this atom list.
-class nsICSSPseudoClass : public nsIAtom {};
-
 class nsCSSPseudoClasses {
 public:
 
   static void AddRefAtoms();
 
-  static PRBool HasStringArg(nsIAtom* aAtom);
-  static PRBool HasNthPairArg(nsIAtom* aAtom);
-  static PRBool HasSelectorListArg(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);
+  static PRBool HasStringArg(Type aType);
+  static PRBool HasNthPairArg(Type aType);
+  static PRBool HasSelectorListArg(Type aType) {
+    return aType == ePseudoClass_any;
+  }
+
+  // Should only be used on types other than Count and NotPseudoClass
+  static void PseudoTypeToString(Type aType, nsAString& aString);
 };
 
 #endif /* nsCSSPseudoClasses_h___ */
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2036,18 +2036,18 @@ nsStyleDisplay::nsStyleDisplay(const nsS
 nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
   if (!EqualURIs(mBinding, aOther.mBinding)
       || mPosition != aOther.mPosition
       || mDisplay != aOther.mDisplay
       || (mFloats == NS_STYLE_FLOAT_NONE) != (aOther.mFloats == NS_STYLE_FLOAT_NONE)
-      || mOverflowX != aOther.mOverflowX
-      || mOverflowY != aOther.mOverflowY
+      || (mOverflowX != aOther.mOverflowX && mDisplay != NS_STYLE_DISPLAY_INLINE)
+      || (mOverflowY != aOther.mOverflowY && mDisplay != NS_STYLE_DISPLAY_INLINE)
       || mResize != aOther.mResize)
     NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
 
   if (mFloats != aOther.mFloats) {
     // Changing which side we float on doesn't affect descendants directly
     NS_UpdateHint(hint,
        NS_SubtractHint(nsChangeHint_ReflowFrame,
                        NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
--- a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
+++ b/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp
@@ -4191,21 +4191,21 @@ nsTreeBodyFrame::GetPseudoStyleContext(n
                                      mStyleContext, aPseudoElement,
                                      mScratchArray);
 }
 
 // Our comparator for resolving our complex pseudos
 PRBool
 nsTreeBodyFrame::PseudoMatches(nsCSSSelector* aSelector)
 {
-  // Iterate the pseudoclass list.  For each item in the list, see if
+  // Iterate the class list.  For each item in the list, see if
   // it is contained in our scratch array.  If we have a miss, then
-  // we aren't a match.  If all items in the pseudoclass list are
+  // we aren't a match.  If all items in the class list are
   // present in the scratch array, then we have a match.
-  nsPseudoClassList* curr = aSelector->mPseudoClassList;
+  nsAtomList* curr = aSelector->mClassList;
   while (curr) {
     PRInt32 index;
     mScratchArray->GetIndexOf(curr->mAtom, &index);
     if (index == -1) {
       return PR_FALSE;
     }
     curr = curr->mNext;
   }
--- a/view/public/nsIView.h
+++ b/view/public/nsIView.h
@@ -57,18 +57,18 @@ class nsIWidget;
 // show - the layer is shown irrespective of the visibility of 
 //        the layer's parent.
 enum nsViewVisibility {
   nsViewVisibility_kHide = 0,
   nsViewVisibility_kShow = 1
 };
 
 #define NS_IVIEW_IID    \
-  { 0xd0c2cf54, 0xb527, 0x4d8e, \
-    { 0xba, 0x87, 0x39, 0x03, 0xa7, 0xc4, 0x13, 0xe1 } }
+  { 0x63052d96, 0x2a4b, 0x434f, \
+    { 0xb4, 0xd3, 0x61, 0x41, 0x83, 0x24, 0x00, 0x76 } }
 
 // Public view flags are defined in this file
 #define NS_VIEW_FLAGS_PUBLIC              0x00FF
 // Private view flags are private to the view module,
 // and are defined in nsView.h
 #define NS_VIEW_FLAGS_PRIVATE             0xFF00
 
 // Public view flags
@@ -320,16 +320,23 @@ public:
    * |aWidgetInitData| must be nonnull.
    */
   nsresult CreateWidgetForPopup(nsWidgetInitData *aWidgetInitData,
                                 nsIWidget* aParentWidget = nsnull,
                                 PRBool aEnableDragDrop = PR_TRUE,
                                 PRBool aResetVisibility = PR_TRUE);
 
   /**
+   * Destroys the associated widget for this view.  If this method is
+   * not called explicitly, the widget when be destroyed when its
+   * view gets destroyed.
+   */
+  void DestroyWidget();
+
+  /**
    * Attach/detach a top level widget from this view. When attached, the view
    * updates the widget's device context and allows the view to begin receiving
    * gecko events. The underlying base window associated with the widget will
    * continues to receive events it expects.
    *
    * An attached widget will not be destroyed when the view is destroyed,
    * allowing the recycling of a single top level widget over multiple views.
    *
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -264,16 +264,27 @@ nsView::~nsView()
     mViewManager = nsnull;
   }
   else if (mParent)
   {
     mParent->RemoveChild(this);
   }
 
   // Destroy and release the widget
+  DestroyWidget();
+
+  delete mDirtyRegion;
+
+  if (mDeletionObserver) {
+    mDeletionObserver->Clear();
+  }
+}
+
+void nsView::DestroyWidget()
+{
   if (mWindow)
   {
     // Release memory for the view wrapper
     ViewWrapper* wrapper = GetWrapperFor(mWindow);
     NS_IF_RELEASE(wrapper);
 
     // If we are not attached to a base window, we're going to tear down our
     // widget here. However, if we're attached to somebody elses widget, we
@@ -287,21 +298,16 @@ nsView::~nsView()
     }
     else {
       mWindow->SetClientData(nsnull);
       mWindow->Destroy();
     }
 
     NS_RELEASE(mWindow);
   }
-  delete mDirtyRegion;
-
-  if (mDeletionObserver) {
-    mDeletionObserver->Clear();
-  }
 }
 
 nsresult nsView::QueryInterface(const nsIID& aIID, void** aInstancePtr)
 {
   if (nsnull == aInstancePtr) {
     return NS_ERROR_NULL_POINTER;
   }
 
@@ -693,16 +699,21 @@ nsresult nsIView::CreateWidgetForPopup(n
                                        nsIWidget* aParentWidget,
                                        PRBool aEnableDragDrop,
                                        PRBool aResetVisibility)
 {
   return Impl()->CreateWidgetForPopup(aWidgetInitData, aParentWidget,
                                       aEnableDragDrop, aResetVisibility);
 }
 
+void nsIView::DestroyWidget()
+{
+  Impl()->DestroyWidget();
+}
+
 struct DefaultWidgetInitData : public nsWidgetInitData {
   DefaultWidgetInitData() : nsWidgetInitData()
   {
     mWindowType = eWindowType_child;
     clipChildren = PR_TRUE;
     clipSiblings = PR_TRUE;
   }
 };
--- a/view/src/nsView.h
+++ b/view/src/nsView.h
@@ -130,16 +130,19 @@ public:
                                  PRBool aResetVisibility);
 
   // See nsIView::CreateWidgetForPopup.
   nsresult CreateWidgetForPopup(nsWidgetInitData *aWidgetInitData,
                                 nsIWidget* aParentWidget,
                                 PRBool aEnableDragDrop,
                                 PRBool aResetVisibility);
 
+  // See nsIView::DestroyWidget
+  void DestroyWidget();
+
   // NOT in nsIView, so only available in view module
   // These are also present in nsIView, but these versions return nsView and nsViewManager
   // instead of nsIView and nsIViewManager.
   nsView* GetFirstChild() const { return mFirstChild; }
   nsView* GetNextSibling() const { return mNextSibling; }
   nsView* GetParent() const { return mParent; }
   nsViewManager* GetViewManager() const { return mViewManager; }
   // These are superseded by a better interface in nsIView