Merge
authorRobert Sayre <sayrer@gmail.com>
Wed, 14 Jul 2010 06:00:55 -0700
changeset 47630 c26c255bade9ba09c0bb7b08586d1035faa74eca
parent 47629 ed584e242da93df69835b848ecd4e97285f19c91 (current diff)
parent 47382 1b4359586ce5d0d883e9c348a75d42cfc2a72220 (diff)
child 47631 0628b5695f2b4d74f6fd88fec77954af76b8ec74
push id14372
push userrsayre@mozilla.com
push dateWed, 14 Jul 2010 13:02:13 +0000
treeherdermozilla-central@c26c255bade9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone2.0b2pre
first release with
nightly win64
c26c255bade9 / 4.0b2pre / 20100714071305 / files
nightly linux32
nightly linux64
nightly mac
nightly win32
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly win64
Merge
content/base/src/nsContentUtils.cpp
dom/base/nsDOMClassInfo.cpp
--- a/accessible/src/base/nsAccessible.cpp
+++ b/accessible/src/base/nsAccessible.cpp
@@ -2183,19 +2183,17 @@ nsAccessible::GetRelationByType(PRUint32
     }
 
   case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON:
     {
       if (mContent->IsHTML()) {
         // HTML form controls implements nsIFormControl interface.
         nsCOMPtr<nsIFormControl> control(do_QueryInterface(mContent));
         if (control) {
-          nsCOMPtr<nsIDOMHTMLFormElement> htmlform;
-          control->GetForm(getter_AddRefs(htmlform));
-          nsCOMPtr<nsIForm> form(do_QueryInterface(htmlform));
+          nsCOMPtr<nsIForm> form(do_QueryInterface(control->GetFormElement()));
           if (form) {
             nsCOMPtr<nsIContent> formContent =
               do_QueryInterface(form->GetDefaultSubmitElement());
             return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
                                                     formContent);
           }
         }
       }
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -165,25 +165,21 @@ void nsBaseContentList::InsertElementAt(
 nsFormContentList::nsFormContentList(nsIDOMHTMLFormElement *aForm,
                                      nsBaseContentList& aContentList)
   : nsBaseContentList()
 {
 
   // move elements that belong to mForm into this content list
 
   PRUint32 i, length = 0;
-  nsCOMPtr<nsIDOMNode> item;
 
   aContentList.GetLength(&length);
 
   for (i = 0; i < length; i++) {
-    aContentList.Item(i, getter_AddRefs(item));
-
-    nsCOMPtr<nsIContent> c(do_QueryInterface(item));
-
+    nsIContent *c = aContentList.GetNodeAt(i);
     if (c && nsContentUtils::BelongsInForm(aForm, c)) {
       AppendElement(c);
     }
   }
 }
 
 // Hashtable for storing nsContentLists
 static PLDHashTable gContentListHashTable;
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -1909,21 +1909,20 @@ static inline void KeyAppendInt(PRInt32 
 
 static inline void KeyAppendAtom(nsIAtom* aAtom, nsACString& aKey)
 {
   NS_PRECONDITION(aAtom, "KeyAppendAtom: aAtom can not be null!\n");
 
   KeyAppendString(nsAtomCString(aAtom), aKey);
 }
 
-static inline PRBool IsAutocompleteOff(nsIDOMElement* aElement)
-{
-  nsAutoString autocomplete;
-  aElement->GetAttribute(NS_LITERAL_STRING("autocomplete"), autocomplete);
-  return autocomplete.LowerCaseEqualsLiteral("off");
+static inline PRBool IsAutocompleteOff(nsIContent* aElement)
+{
+  return aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::autocomplete,
+                               NS_LITERAL_STRING("off"), eIgnoreCase);
 }
 
 /*static*/ nsresult
 nsContentUtils::GenerateStateKey(nsIContent* aContent,
                                  nsIDocument* aDocument,
                                  nsIStatefulFrame::SpecialStateID aID,
                                  nsACString& aKey)
 {
@@ -1942,18 +1941,17 @@ nsContentUtils::GenerateStateKey(nsICont
   // We must have content if we're not using a special state id
   NS_ENSURE_TRUE(aContent, NS_ERROR_FAILURE);
 
   // Don't capture state for anonymous content
   if (aContent->IsInAnonymousSubtree()) {
     return NS_OK;
   }
 
-  nsCOMPtr<nsIDOMElement> element(do_QueryInterface(aContent));
-  if (element && IsAutocompleteOff(element)) {
+  if (IsAutocompleteOff(aContent)) {
     return NS_OK;
   }
 
   nsCOMPtr<nsIHTMLDocument> htmlDocument(do_QueryInterface(aContent->GetCurrentDoc()));
 
   KeyAppendInt(partID, aKey);  // first append a partID
   // Make sure we can't possibly collide with an nsIStatefulFrame
   // special id of some sort
@@ -1989,30 +1987,27 @@ nsContentUtils::GenerateStateKey(nsICont
     nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
     if (control && htmlFormControls && htmlForms) {
 
       // Append the control type
       KeyAppendInt(control->GetType(), aKey);
 
       // If in a form, add form name / index of form / index in form
       PRInt32 index = -1;
-      nsCOMPtr<nsIDOMHTMLFormElement> formElement;
-      control->GetForm(getter_AddRefs(formElement));
+      Element *formElement = control->GetFormElement();
       if (formElement) {
-
         if (IsAutocompleteOff(formElement)) {
           aKey.Truncate();
           return NS_OK;
         }
 
         KeyAppendString(NS_LITERAL_CSTRING("f"), aKey);
 
         // Append the index of the form in the document
-        nsCOMPtr<nsIContent> formContent(do_QueryInterface(formElement));
-        index = htmlForms->IndexOf(formContent, PR_FALSE);
+        index = htmlForms->IndexOf(formElement, PR_FALSE);
         if (index <= -1) {
           //
           // XXX HACK this uses some state that was dumped into the document
           // specifically to fix bug 138892.  What we are trying to do is *guess*
           // which form this control's state is found in, with the highly likely
           // guess that the highest form parsed so far is the one.
           // This code should not be on trunk, only branch.
           //
@@ -2028,17 +2023,17 @@ nsContentUtils::GenerateStateKey(nsICont
           if (index > -1) {
             KeyAppendInt(index, aKey);
             generatedUniqueKey = PR_TRUE;
           }
         }
 
         // Append the form name
         nsAutoString formName;
-        formElement->GetName(formName);
+        formElement->GetAttr(kNameSpaceID_None, nsGkAtoms::name, formName);
         KeyAppendString(formName, aKey);
 
       } else {
 
         KeyAppendString(NS_LITERAL_CSTRING("d"), aKey);
 
         // If not in a form, add index of control in document
         // Less desirable than indexing by form info.
--- a/content/base/src/nsDOMAttributeMap.cpp
+++ b/content/base/src/nsDOMAttributeMap.cpp
@@ -67,21 +67,20 @@ nsDOMAttributeMap::Init()
 {
   return mAttributeCache.Init();
 }
 
 /**
  * Clear map pointer for attributes.
  */
 PLDHashOperator
-RemoveMapRef(nsAttrHashKey::KeyType aKey, nsCOMPtr<nsIDOMNode>& aData, void* aUserArg)
+RemoveMapRef(nsAttrHashKey::KeyType aKey, nsRefPtr<nsDOMAttribute>& aData,
+             void* aUserArg)
 {
-  nsCOMPtr<nsIAttribute> attr(do_QueryInterface(aData));
-  NS_ASSERTION(attr, "non-nsIAttribute somehow made it into the hashmap?!");
-  attr->SetMap(nsnull);
+  aData->SetMap(nsnull);
 
   return PL_DHASH_REMOVE;
 }
 
 nsDOMAttributeMap::~nsDOMAttributeMap()
 {
   mAttributeCache.Enumerate(RemoveMapRef, nsnull);
 }
@@ -96,22 +95,23 @@ nsDOMAttributeMap::DropReference()
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMAttributeMap)
   tmp->DropReference();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 PLDHashOperator
-TraverseMapEntry(nsAttrHashKey::KeyType aKey, nsCOMPtr<nsIDOMNode>& aData, void* aUserArg)
+TraverseMapEntry(nsAttrHashKey::KeyType aKey, nsRefPtr<nsDOMAttribute>& aData,
+                 void* aUserArg)
 {
   nsCycleCollectionTraversalCallback *cb = 
     static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
 
-  cb->NoteXPCOMChild(aData.get());
+  cb->NoteXPCOMChild(static_cast<nsINode*>(aData.get()));
 
   return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMAttributeMap)
   tmp->mAttributeCache.Enumerate(TraverseMapEntry, &cb);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
@@ -126,22 +126,21 @@ NS_INTERFACE_TABLE_HEAD(nsDOMAttributeMa
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsDOMAttributeMap)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(NamedNodeMap)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMAttributeMap)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMAttributeMap)
 
 PLDHashOperator
-SetOwnerDocumentFunc(nsAttrHashKey::KeyType aKey, nsCOMPtr<nsIDOMNode>& aData,
+SetOwnerDocumentFunc(nsAttrHashKey::KeyType aKey,
+                     nsRefPtr<nsDOMAttribute>& aData,
                      void* aUserArg)
 {
-  nsCOMPtr<nsIAttribute> attr(do_QueryInterface(aData));
-  NS_ASSERTION(attr, "non-nsIAttribute somehow made it into the hashmap?!");
-  nsresult rv = attr->SetOwnerDocument(static_cast<nsIDocument*>(aUserArg));
+  nsresult rv = aData->SetOwnerDocument(static_cast<nsIDocument*>(aUserArg));
 
   return NS_FAILED(rv) ? PL_DHASH_STOP : PL_DHASH_NEXT;
 }
 
 nsresult
 nsDOMAttributeMap::SetOwnerDocument(nsIDocument* aDocument)
 {
   PRUint32 n = mAttributeCache.Enumerate(SetOwnerDocumentFunc, aDocument);
@@ -149,98 +148,90 @@ nsDOMAttributeMap::SetOwnerDocument(nsID
 
   return NS_OK;
 }
 
 void
 nsDOMAttributeMap::DropAttribute(PRInt32 aNamespaceID, nsIAtom* aLocalName)
 {
   nsAttrKey attr(aNamespaceID, aLocalName);
-  nsIDOMNode *node = mAttributeCache.GetWeak(attr);
+  nsDOMAttribute *node = mAttributeCache.GetWeak(attr);
   if (node) {
-    nsCOMPtr<nsIAttribute> iAttr(do_QueryInterface(node));
-    NS_ASSERTION(iAttr, "non-nsIAttribute somehow made it into the hashmap?!");
-
     // Break link to map
-    iAttr->SetMap(nsnull);
+    node->SetMap(nsnull);
 
     // Remove from cache
     mAttributeCache.Remove(attr);
   }
 }
 
 nsresult
 nsDOMAttributeMap::RemoveAttribute(nsINodeInfo* aNodeInfo, nsIDOMNode** aReturn)
 {
   NS_ASSERTION(aNodeInfo, "RemoveAttribute() called with aNodeInfo == nsnull!");
   NS_ASSERTION(aReturn, "RemoveAttribute() called with aReturn == nsnull");
 
   *aReturn = nsnull;
 
   nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
 
-  if (!mAttributeCache.Get(attr, aReturn)) {
+  nsRefPtr<nsDOMAttribute> node;
+  if (!mAttributeCache.Get(attr, getter_AddRefs(node))) {
     nsAutoString value;
     // As we are removing the attribute we need to set the current value in
     // the attribute node.
     mContent->GetAttr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom(), value);
     nsCOMPtr<nsIDOMNode> newAttr = new nsDOMAttribute(nsnull, aNodeInfo, value);
     if (!newAttr) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
     newAttr.swap(*aReturn);
   }
   else {
-    nsCOMPtr<nsIAttribute> iAttr(do_QueryInterface(*aReturn));
-    NS_ASSERTION(iAttr, "non-nsIAttribute somehow made it into the hashmap?!");
-
     // Break link to map
-    iAttr->SetMap(nsnull);
+    node->SetMap(nsnull);
 
     // Remove from cache
     mAttributeCache.Remove(attr);
+
+    node.forget(aReturn);
   }
 
   return NS_OK;
 }
 
-nsIDOMNode*
+nsDOMAttribute*
 nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo)
 {
   NS_ASSERTION(aNodeInfo, "GetAttribute() called with aNodeInfo == nsnull!");
 
   nsAttrKey attr(aNodeInfo->NamespaceID(), aNodeInfo->NameAtom());
 
-  nsIDOMNode* node = mAttributeCache.GetWeak(attr);
+  nsDOMAttribute* node = mAttributeCache.GetWeak(attr);
   if (!node) {
-    nsCOMPtr<nsIDOMNode> newAttr =
+    nsRefPtr<nsDOMAttribute> newAttr =
       new nsDOMAttribute(this, aNodeInfo, EmptyString());
     if (newAttr && mAttributeCache.Put(attr, newAttr)) {
       node = newAttr;
     }
   }
 
   return node;
 }
 
-nsIDOMNode*
+nsDOMAttribute*
 nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName, nsresult *aResult)
 {
   *aResult = NS_OK;
 
   if (mContent) {
     nsCOMPtr<nsINodeInfo> ni =
       mContent->GetExistingAttrNameFromQName(aAttrName);
     if (ni) {
-      nsIDOMNode* node = GetAttribute(ni);
-      if (node) {
-        return node;
-      }
-
-      *aResult = NS_ERROR_OUT_OF_MEMORY;
+      return GetAttribute(ni);
     }
   }
 
   return nsnull;
 }
 
 NS_IMETHODIMP
 nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName,
@@ -277,22 +268,23 @@ nsDOMAttributeMap::SetNamedItemInternal(
   nsresult rv = NS_OK;
   *aReturn = nsnull;
   nsCOMPtr<nsIDOMNode> tmpReturn;
 
   if (mContent) {
     // XXX should check same-origin between mContent and aNode however
     // nsContentUtils::CheckSameOrigin can't deal with attributenodes yet
     
-    nsCOMPtr<nsIDOMAttr> attribute(do_QueryInterface(aNode));
     nsCOMPtr<nsIAttribute> iAttribute(do_QueryInterface(aNode));
-    if (!attribute || !iAttribute) {
+    if (!iAttribute) {
       return NS_ERROR_DOM_HIERARCHY_REQUEST_ERR;
     }
 
+    nsDOMAttribute *attribute = static_cast<nsDOMAttribute*>(iAttribute.get());
+
     // Check that attribute is not owned by somebody else
     nsDOMAttributeMap* owner = iAttribute->GetMap();
     if (owner) {
       if (owner != this) {
         return NS_ERROR_DOM_INUSE_ATTRIBUTE_ERR;
       }
 
       // setting a preexisting attribute is a no-op, just return the same
@@ -384,45 +376,44 @@ nsDOMAttributeMap::RemoveNamedItem(const
   nsresult rv = NS_OK;
 
   if (mContent) {
     nsCOMPtr<nsINodeInfo> ni = mContent->GetExistingAttrNameFromQName(aName);
     if (!ni) {
       return NS_ERROR_DOM_NOT_FOUND_ERR;
     }
 
-    rv = GetAttribute(ni, aReturn);
-    NS_ENSURE_SUCCESS(rv, rv);
+    NS_ADDREF(*aReturn = GetAttribute(ni));
 
     // This removes the attribute node from the attribute map.
     rv = mContent->UnsetAttr(ni->NamespaceID(), ni->NameAtom(), PR_TRUE);
   }
 
   return rv;
 }
 
 
-nsIDOMNode*
+nsDOMAttribute*
 nsDOMAttributeMap::GetItemAt(PRUint32 aIndex, nsresult *aResult)
 {
   *aResult = NS_OK;
 
-  nsIDOMNode* node = nsnull;
+  nsDOMAttribute* node = nsnull;
 
   const nsAttrName* name;
   if (mContent && (name = mContent->GetAttrNameAt(aIndex))) {
     // Don't use the nodeinfo even if one exists since it can
     // have the wrong owner document.
     nsCOMPtr<nsINodeInfo> ni;
     ni = mContent->NodeInfo()->NodeInfoManager()->
       GetNodeInfo(name->LocalName(), name->GetPrefix(), name->NamespaceID());
     if (ni) {
       node = GetAttribute(ni);
     }
-    if (!node) {
+    else {
       *aResult = NS_ERROR_OUT_OF_MEMORY;
     }
   }
 
   return node;
 }
 
 NS_IMETHODIMP
@@ -488,17 +479,21 @@ nsDOMAttributeMap::GetNamedItemNSInterna
 
     if (nameSpaceID == attrNS &&
         nameAtom->Equals(aLocalName)) {
       nsCOMPtr<nsINodeInfo> ni;
       ni = mContent->NodeInfo()->NodeInfoManager()->
         GetNodeInfo(nameAtom, name->GetPrefix(), nameSpaceID);
       NS_ENSURE_TRUE(ni, NS_ERROR_OUT_OF_MEMORY);
 
-      return aRemove ? RemoveAttribute(ni, aReturn) : GetAttribute(ni, aReturn);
+      if (aRemove) {
+        return RemoveAttribute(ni, aReturn);
+      }
+
+      NS_ADDREF(*aReturn = GetAttribute(ni));
     }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI,
--- a/content/base/src/nsDOMAttributeMap.h
+++ b/content/base/src/nsDOMAttributeMap.h
@@ -40,17 +40,17 @@
  * Implementation of the |attributes| property of DOM Core's nsIDOMNode object.
  */
 
 #ifndef nsDOMAttributeMap_h___
 #define nsDOMAttributeMap_h___
 
 #include "nsIDOMNamedNodeMap.h"
 #include "nsString.h"
-#include "nsInterfaceHashtable.h"
+#include "nsRefPtrHashtable.h"
 #include "nsCycleCollectionParticipant.h"
 #include "prbit.h"
 #include "nsIDOMNode.h"
 
 class nsIAtom;
 class nsIContent;
 class nsDOMAttribute;
 class nsINodeInfo;
@@ -155,28 +155,28 @@ public:
    * Returns the number of attribute nodes currently in the map.
    * Note: this is just the number of cached attribute nodes, not the number of
    * attributes in mContent.
    *
    * @return The number of attribute nodes in the map.
    */
   PRUint32 Count() const;
 
-  typedef nsInterfaceHashtable<nsAttrHashKey, nsIDOMNode> AttrCache;
+  typedef nsRefPtrHashtable<nsAttrHashKey, nsDOMAttribute> AttrCache;
 
   /**
    * Enumerates over the attribute nodess in the map and calls aFunc for each
    * one. If aFunc returns PL_DHASH_STOP we'll stop enumerating at that point.
    *
    * @return The number of attribute nodes that aFunc was called for.
    */
   PRUint32 Enumerate(AttrCache::EnumReadFunction aFunc, void *aUserArg) const;
 
-  nsIDOMNode* GetItemAt(PRUint32 aIndex, nsresult *rv);
-  nsIDOMNode* GetNamedItem(const nsAString& aAttrName, nsresult *rv);
+  nsDOMAttribute* GetItemAt(PRUint32 aIndex, nsresult *rv);
+  nsDOMAttribute* GetNamedItem(const nsAString& aAttrName, nsresult *rv);
 
   static nsDOMAttributeMap* FromSupports(nsISupports* aSupports)
   {
 #ifdef DEBUG
     {
       nsCOMPtr<nsIDOMNamedNodeMap> map_qi = do_QueryInterface(aSupports);
 
       // If this assertion fires the QI implementation for the object in
@@ -212,34 +212,17 @@ private:
    * GetNamedItemNS() implementation taking |aRemove| for GetAttribute(),
    * which is used by RemoveNamedItemNS().
    */
   nsresult GetNamedItemNSInternal(const nsAString& aNamespaceURI,
                                   const nsAString& aLocalName,
                                   nsIDOMNode** aReturn,
                                   PRBool aRemove = PR_FALSE);
 
-  /**
-   * Returns an attribute, either by retrieving it from the cache or by
-   * creating a new one.
-   */
-  nsresult GetAttribute(nsINodeInfo*     aNodeInfo,
-                        nsIDOMNode**     aReturn)
-  {
-    *aReturn = GetAttribute(aNodeInfo);
-    if (!*aReturn) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    NS_ADDREF(*aReturn);
-
-    return NS_OK;
-  }
-
-  nsIDOMNode* GetAttribute(nsINodeInfo*     aNodeInfo);
+  nsDOMAttribute* GetAttribute(nsINodeInfo* aNodeInfo);
 
   /**
    * Remove an attribute, returns the removed node.
    */
   nsresult RemoveAttribute(nsINodeInfo*     aNodeInfo,
                            nsIDOMNode**     aReturn);
 };
 
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5614,22 +5614,22 @@ nsDocument::SetDocumentURI(const nsAStri
   // Not allowing this yet, need to think about security ramifications first.
   // We use mDocumentURI to get principals for this document.
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 static void BlastSubtreeToPieces(nsINode *aNode);
 
 PLDHashOperator
-BlastFunc(nsAttrHashKey::KeyType aKey, nsIDOMNode *aData, void* aUserArg)
+BlastFunc(nsAttrHashKey::KeyType aKey, nsDOMAttribute *aData, void* aUserArg)
 {
   nsCOMPtr<nsIAttribute> *attr =
     static_cast<nsCOMPtr<nsIAttribute>*>(aUserArg);
 
-  *attr = do_QueryInterface(aData);
+  *attr = aData;
 
   NS_ASSERTION(attr->get(),
                "non-nsIAttribute somehow made it into the hashmap?!");
 
   return PL_DHASH_STOP;
 }
 
 static void
--- a/content/base/src/nsNodeUtils.h
+++ b/content/base/src/nsNodeUtils.h
@@ -33,24 +33,23 @@
  * 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 ***** */
 
 #ifndef nsNodeUtils_h___
 #define nsNodeUtils_h___
 
-#include "nsDOMAttributeMap.h"
-#include "nsIDOMNode.h"
 #include "nsINode.h"
 
 struct CharacterDataChangeInfo;
 struct JSContext;
 struct JSObject;
 class nsIVariant;
+class nsIDOMNode;
 class nsIDOMUserDataHandler;
 template<class E> class nsCOMArray;
 class nsCycleCollectionTraversalCallback;
 
 class nsNodeUtils
 {
 public:
   /**
@@ -245,19 +244,16 @@ public:
   /**
    * Release the UserData and UserDataHandlers for aNode.
    *
    * @param aNode the node to release the UserData and UserDataHandlers for
    */
   static void UnlinkUserData(nsINode *aNode);
 
 private:
-  friend PLDHashOperator
-    AdoptFunc(nsAttrHashKey::KeyType aKey, nsIDOMNode *aData, void* aUserArg);
-
   /**
    * Walks aNode, its attributes and, if aDeep is PR_TRUE, its descendant nodes.
    * If aClone is PR_TRUE the nodes will be cloned. If aNewNodeInfoManager is
    * not null, it is used to create new nodeinfos for the nodes. Also reparents
    * the XPConnect wrappers for the nodes in aNewScope if aCx is not null.
    * aNodesWithProperties will be filled with all the nodes that have
    * properties.
    *
--- a/content/html/content/public/nsIFormControl.h
+++ b/content/html/content/public/nsIFormControl.h
@@ -40,16 +40,22 @@
 #include "nsISupports.h"
 class nsIDOMHTMLFormElement;
 class nsPresState;
 class nsIContent;
 class nsString;
 class nsIFormProcessor;
 class nsFormSubmission;
 
+namespace mozilla {
+namespace dom {
+class Element;
+} // namespace dom
+} // namespace mozilla
+
 enum FormControlsTypes {
   NS_FORM_FIELDSET = 1,
   NS_FORM_LABEL,
   NS_FORM_OUTPUT,
   NS_FORM_SELECT,
   NS_FORM_TEXTAREA,
   NS_FORM_OBJECT,
   eFormControlsWithoutSubTypesMax,
@@ -88,35 +94,35 @@ enum InputElementTypes {
   eInputElementTypesMax
 };
 
 PR_STATIC_ASSERT((PRUint32)eFormControlsWithoutSubTypesMax < (PRUint32)NS_FORM_BUTTON_ELEMENT);
 PR_STATIC_ASSERT((PRUint32)eButtonElementTypesMax < (PRUint32)NS_FORM_INPUT_ELEMENT);
 PR_STATIC_ASSERT((PRUint32)eInputElementTypesMax  < 1<<8);
 
 #define NS_IFORMCONTROL_IID   \
-{ 0x52dc1f0d, 0x1683, 0x4dd7, \
- { 0xae, 0x0a, 0xc4, 0x76, 0x10, 0x64, 0x2f, 0xa8 } }
+{ 0x0dc5083b, 0xb0a8, 0x48c4, \
+ { 0xb2, 0xeb, 0xc2, 0x4f, 0xfb, 0x7e, 0xc2, 0x8e } }
 
 /**
  * Interface which all form controls (e.g. buttons, checkboxes, text,
  * radio buttons, select, etc) implement in addition to their dom specific
  * interface.
  */
 class nsIFormControl : public nsISupports
 {
 public:
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFORMCONTROL_IID)
 
   /**
    * Get the form for this form control.
-   * @param aForm the form [OUT]
+   * @return the form
    */
-  NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm) = 0;
+  virtual mozilla::dom::Element *GetFormElement() = 0;
 
   /**
    * Set the form for this form control.
    * @param aForm the form.  This must not be null.
    *
    * @note that when setting the form the control is not added to the
    * form.  It adds itself when it gets bound to the tree thereafter,
    * so that it can be properly sorted with the other controls in the
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -106,16 +106,19 @@
 #include "nsIEditor.h"
 #include "nsIEditorIMESupport.h"
 #include "nsEventDispatcher.h"
 #include "nsLayoutUtils.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozAutoDocUpdate.h"
 #include "nsHtml5Module.h"
 #include "nsITextControlElement.h"
+#include "mozilla/dom/Element.h"
+
+using namespace mozilla::dom;
 
 #include "nsThreadUtils.h"
 
 class nsINodeInfo;
 class nsIDOMNodeList;
 class nsRuleWalker;
 
 // XXX todo: add in missing out-of-memory checks
@@ -2374,17 +2377,23 @@ nsGenericHTMLFormElement::ClearForm(PRBo
       mForm->RemoveElementFromTable(this, idVal);
     }
   }
 
   UnsetFlags(ADDED_TO_FORM);
   mForm = nsnull;
 }
 
-NS_IMETHODIMP
+Element*
+nsGenericHTMLFormElement::GetFormElement()
+{
+  return mForm;
+}
+
+nsresult
 nsGenericHTMLFormElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
   NS_ENSURE_ARG_POINTER(aForm);
   NS_IF_ADDREF(*aForm = mForm);
   return NS_OK;
 }
 
 PRUint32
--- a/content/html/content/src/nsGenericHTMLElement.h
+++ b/content/html/content/src/nsGenericHTMLElement.h
@@ -798,20 +798,22 @@ public:
   virtual ~nsGenericHTMLFormElement();
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
 
   virtual PRBool IsNodeOfType(PRUint32 aFlags) const;
   virtual void SaveSubtreeState();
 
   // nsIFormControl
-  NS_IMETHOD GetForm(nsIDOMHTMLFormElement** aForm);
+  virtual mozilla::dom::Element* GetFormElement();
   virtual void SetForm(nsIDOMHTMLFormElement* aForm);
   virtual void ClearForm(PRBool aRemoveFromForm, PRBool aNotify);
 
+  nsresult GetForm(nsIDOMHTMLFormElement** aForm);
+
   NS_IMETHOD SaveState()
   {
     return NS_OK;
   }
   
   virtual PRBool RestoreState(nsPresState* aState)
   {
     return PR_FALSE;
--- a/content/html/content/src/nsHTMLFormElement.h
+++ b/content/html/content/src/nsHTMLFormElement.h
@@ -43,16 +43,17 @@
 #include "nsIDOMNSHTMLFormElement.h"
 #include "nsIWebProgressListener.h"
 #include "nsIRadioGroupContainer.h"
 #include "nsIURI.h"
 #include "nsIWeakReferenceUtils.h"
 #include "nsPIDOMWindow.h"
 #include "nsUnicharUtils.h"
 #include "nsThreadUtils.h"
+#include "nsInterfaceHashtable.h"
 
 class nsFormControlList;
 
 /**
  * hashkey wrapper using nsAString KeyType
  *
  * @see nsTHashtable::EntryType for specification
  */
--- a/content/html/content/src/nsHTMLLegendElement.cpp
+++ b/content/html/content/src/nsHTMLLegendElement.cpp
@@ -30,92 +30,29 @@
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * 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 "nsIDOMHTMLLegendElement.h"
+#include "nsHTMLLegendElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMEventTarget.h"
-#include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIForm.h"
 #include "nsIFormControl.h"
 #include "nsIEventStateManager.h"
 #include "nsIDocument.h"
 #include "nsPIDOMWindow.h"
 #include "nsFocusManager.h"
 #include "nsIFrame.h"
 
-class nsHTMLLegendElement : public nsGenericHTMLElement,
-                            public nsIDOMHTMLLegendElement
-{
-public:
-  nsHTMLLegendElement(nsINodeInfo *aNodeInfo);
-  virtual ~nsHTMLLegendElement();
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
-
-  // nsIDOMElement
-  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
-
-  // nsIDOMHTMLElement
-  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
-
-  // nsIDOMHTMLLegendElement
-  NS_DECL_NSIDOMHTMLLEGENDELEMENT
-
-  // nsGenericHTMLElement
-  NS_IMETHODIMP Focus();
-
-  virtual void PerformAccesskey(PRBool aKeyCausesActivation,
-                                PRBool aIsTrustedEvent);
-
-  // nsIContent
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              PRBool aCompileEventHandlers);
-  virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
-                              PRBool aNullParent = PR_TRUE);
-  virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
-                                nsIAtom* aAttribute,
-                                const nsAString& aValue,
-                                nsAttrValue& aResult);
-  virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
-                                              PRInt32 aModType) const;
-  nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
-                   const nsAString& aValue, PRBool aNotify)
-  {
-    return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
-  }
-  virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
-                           nsIAtom* aPrefix, const nsAString& aValue,
-                           PRBool aNotify);
-  virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
-                             PRBool aNotify);
-
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-protected:
-  /**
-   * Get the fieldset content element that contains this legend.
-   * Returns null if there is no fieldset containing this legend.
-   */
-  nsIContent* GetFieldSet();
-};
-
-
 NS_IMPL_NS_NEW_HTML_ELEMENT(Legend)
 
 
 nsHTMLLegendElement::nsHTMLLegendElement(nsINodeInfo *aNodeInfo)
   : nsGenericHTMLElement(aNodeInfo)
 {
 }
 
@@ -142,21 +79,19 @@ NS_HTML_CONTENT_INTERFACE_TABLE_TAIL_CLA
 
 
 NS_IMPL_ELEMENT_CLONE(nsHTMLLegendElement)
 
 
 NS_IMETHODIMP
 nsHTMLLegendElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
-  *aForm = nsnull;
+  Element *form = GetFormElement();
 
-  nsCOMPtr<nsIFormControl> fieldsetControl = do_QueryInterface(GetFieldSet());
-
-  return fieldsetControl ? fieldsetControl->GetForm(aForm) : NS_OK;
+  return form ? CallQueryInterface(form, aForm) : NS_OK;
 }
 
 
 NS_IMPL_STRING_ATTR(nsHTMLLegendElement, AccessKey, accesskey)
 NS_IMPL_STRING_ATTR(nsHTMLLegendElement, Align, align)
 
 // this contains center, because IE4 does
 static const nsAttrValue::EnumTable kAlignTable[] = {
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsHTMLLegendElement.h
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Mats Palmgren <mats.palmgren@bredband.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * 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 ***** */
+#ifndef nsHTMLLegendElement_h___
+#define nsHTMLLegendElement_h___
+
+#include "nsIDOMHTMLLegendElement.h"
+#include "nsGenericHTMLElement.h"
+
+class nsHTMLLegendElement : public nsGenericHTMLElement,
+                            public nsIDOMHTMLLegendElement
+{
+public:
+  nsHTMLLegendElement(nsINodeInfo *aNodeInfo);
+  virtual ~nsHTMLLegendElement();
+
+  static nsHTMLLegendElement* FromContent(nsIContent *aContent)
+  {
+    if (aContent->IsHTML() && aContent->Tag() == nsGkAtoms::legend)
+      return static_cast<nsHTMLLegendElement*>(aContent);
+    return nsnull;
+  }
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsIDOMNode
+  NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
+
+  // nsIDOMElement
+  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
+
+  // nsIDOMHTMLElement
+  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
+
+  // nsIDOMHTMLLegendElement
+  NS_DECL_NSIDOMHTMLLEGENDELEMENT
+
+  // nsGenericHTMLElement
+  NS_IMETHODIMP Focus();
+
+  virtual void PerformAccesskey(PRBool aKeyCausesActivation,
+                                PRBool aIsTrustedEvent);
+
+  // nsIContent
+  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
+                              nsIContent* aBindingParent,
+                              PRBool aCompileEventHandlers);
+  virtual void UnbindFromTree(PRBool aDeep = PR_TRUE,
+                              PRBool aNullParent = PR_TRUE);
+  virtual PRBool ParseAttribute(PRInt32 aNamespaceID,
+                                nsIAtom* aAttribute,
+                                const nsAString& aValue,
+                                nsAttrValue& aResult);
+  virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
+                                              PRInt32 aModType) const;
+  nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+                   const nsAString& aValue, PRBool aNotify)
+  {
+    return SetAttr(aNameSpaceID, aName, nsnull, aValue, aNotify);
+  }
+  virtual nsresult SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
+                           nsIAtom* aPrefix, const nsAString& aValue,
+                           PRBool aNotify);
+  virtual nsresult UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aAttribute,
+                             PRBool aNotify);
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  mozilla::dom::Element *GetFormElement()
+  {
+    nsCOMPtr<nsIFormControl> fieldsetControl = do_QueryInterface(GetFieldSet());
+
+    return fieldsetControl ? fieldsetControl->GetFormElement() : nsnull;
+  }
+
+protected:
+  /**
+   * Get the fieldset content element that contains this legend.
+   * Returns null if there is no fieldset containing this legend.
+   */
+  nsIContent* GetFieldSet();
+};
+
+#endif /* nsHTMLLegendElement_h___ */
--- a/content/html/content/src/nsHTMLOptionElement.cpp
+++ b/content/html/content/src/nsHTMLOptionElement.cpp
@@ -32,116 +32,44 @@
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * 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 "nsIDOMHTMLOptionElement.h"
-#include "nsIDOMNSHTMLOptionElement.h"
-#include "nsIOptionElement.h"
+#include "nsHTMLOptionElement.h"
 #include "nsIDOMHTMLOptGroupElement.h"
 #include "nsIDOMHTMLFormElement.h"
 #include "nsIDOMEventTarget.h"
-#include "nsGenericHTMLElement.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsIFormControl.h"
 #include "nsIForm.h"
 #include "nsIDOMText.h"
 #include "nsIDOMNode.h"
 #include "nsGenericElement.h"
 #include "nsIDOMHTMLCollection.h"
-#include "nsIJSNativeInitializer.h"
 #include "nsISelectElement.h"
 #include "nsISelectControlFrame.h"
 
 // Notify/query select frame for selected state
 #include "nsIFormControlFrame.h"
 #include "nsIDocument.h"
 #include "nsIFrame.h"
 #include "nsIDOMHTMLSelectElement.h"
 #include "nsNodeInfoManager.h"
 #include "nsCOMPtr.h"
 #include "nsIEventStateManager.h"
 #include "nsIDocument.h"
 #include "nsIDOMDocument.h"
 #include "nsContentCreatorFunctions.h"
 #include "mozAutoDocUpdate.h"
 
-/**
- * Implementation of &lt;option&gt;
- */
-class nsHTMLOptionElement : public nsGenericHTMLElement,
-                            public nsIDOMHTMLOptionElement,
-                            public nsIDOMNSHTMLOptionElement,
-                            public nsIJSNativeInitializer,
-                            public nsIOptionElement
-{
-public:
-  nsHTMLOptionElement(nsINodeInfo *aNodeInfo);
-  virtual ~nsHTMLOptionElement();
-
-  // nsISupports
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsIDOMNode
-  NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
-
-  // nsIDOMElement
-  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
-
-  // nsIDOMHTMLElement
-  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
-
-  // nsIDOMHTMLOptionElement
-  NS_DECL_NSIDOMHTMLOPTIONELEMENT
-
-  // nsIDOMNSHTMLOptionElement
-  NS_IMETHOD SetText(const nsAString & aText); 
-
-  // nsIJSNativeInitializer
-  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
-                        JSObject *aObj, PRUint32 argc, jsval *argv);
-
-  virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
-                                              PRInt32 aModType) const;
-
-  virtual nsresult BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
-                                 const nsAString* aValue, PRBool aNotify);
-  
-  // nsIOptionElement
-  NS_IMETHOD SetSelectedInternal(PRBool aValue, PRBool aNotify);
-
-  // nsIContent
-  virtual PRInt32 IntrinsicState() const;
-
-  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
-
-  nsresult CopyInnerTo(nsGenericElement* aDest) const;
-
-protected:
-  /**
-   * Get the select content element that contains this option, this
-   * intentionally does not return nsresult, all we care about is if
-   * there's a select associated with this option or not.
-   * @param aSelectElement the select element (out param)
-   */
-  nsIContent* GetSelect();
-
-  PRPackedBool mSelectedChanged;
-  PRPackedBool mIsSelected;
-
-  // True only while we're under the SetOptionsSelectedByIndex call when our
-  // "selected" attribute is changing and mSelectedChanged is false.
-  PRPackedBool mIsInSetDefaultSelected;
-};
-
 nsGenericHTMLElement*
 NS_NewHTMLOptionElement(nsINodeInfo *aNodeInfo, PRUint32 aFromParser)
 {
   /*
    * nsHTMLOptionElement's will be created without a nsINodeInfo passed in
    * if someone says "var opt = new Option();" in JavaScript, in a case like
    * that we request the nsINodeInfo from the document's nodeinfo list.
    */
@@ -196,17 +124,18 @@ NS_IMPL_ELEMENT_CLONE(nsHTMLOptionElemen
 
 
 NS_IMETHODIMP
 nsHTMLOptionElement::GetForm(nsIDOMHTMLFormElement** aForm)
 {
   NS_ENSURE_ARG_POINTER(aForm);
   *aForm = nsnull;
 
-  nsCOMPtr<nsIFormControl> selectControl = do_QueryInterface(GetSelect());
+  nsCOMPtr<nsIDOMHTMLSelectElement> selectControl =
+    do_QueryInterface(GetSelect());
 
   if (selectControl) {
     selectControl->GetForm(aForm);
   }
 
   return NS_OK;
 }
 
new file mode 100644
--- /dev/null
+++ b/content/html/content/src/nsHTMLOptionElement.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=78: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Communicator client code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Pierre Phaneuf <pp@ludusdesign.com>
+ *   Mats Palmgren <mats.palmgren@bredband.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * 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 ***** */
+
+#ifndef nsHTMLOptionElement_h___
+#define nsHTMLOptionElement_h___
+
+#include "nsIDOMHTMLOptionElement.h"
+#include "nsIDOMNSHTMLOptionElement.h"
+#include "nsIOptionElement.h"
+#include "nsGenericHTMLElement.h"
+#include "nsIJSNativeInitializer.h"
+
+/**
+ * Implementation of &lt;option&gt;
+ */
+class nsHTMLOptionElement : public nsGenericHTMLElement,
+                            public nsIDOMHTMLOptionElement,
+                            public nsIDOMNSHTMLOptionElement,
+                            public nsIJSNativeInitializer,
+                            public nsIOptionElement
+{
+public:
+  nsHTMLOptionElement(nsINodeInfo *aNodeInfo);
+  virtual ~nsHTMLOptionElement();
+
+  /** Typesafe, non-refcounting cast from nsIContent.  Cheaper than QI. **/
+  static nsHTMLOptionElement* FromContent(nsIContent *aContent)
+  {
+    if (aContent->NodeInfo()->Equals(nsGkAtoms::option, kNameSpaceID_XHTML))
+      return static_cast<nsHTMLOptionElement*>(aContent);
+    return nsnull;
+  }
+
+  // nsISupports
+  NS_DECL_ISUPPORTS_INHERITED
+
+  // nsIDOMNode
+  NS_FORWARD_NSIDOMNODE(nsGenericHTMLElement::)
+
+  // nsIDOMElement
+  NS_FORWARD_NSIDOMELEMENT(nsGenericHTMLElement::)
+
+  // nsIDOMHTMLElement
+  NS_FORWARD_NSIDOMHTMLELEMENT(nsGenericHTMLElement::)
+
+  // nsIDOMHTMLOptionElement
+  NS_DECL_NSIDOMHTMLOPTIONELEMENT
+
+  // nsIDOMNSHTMLOptionElement
+  NS_IMETHOD SetText(const nsAString & aText); 
+
+  // nsIJSNativeInitializer
+  NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
+                        JSObject *aObj, PRUint32 argc, jsval *argv);
+
+  virtual nsChangeHint GetAttributeChangeHint(const nsIAtom* aAttribute,
+                                              PRInt32 aModType) const;
+
+  virtual nsresult BeforeSetAttr(PRInt32 aNamespaceID, nsIAtom* aName,
+                                 const nsAString* aValue, PRBool aNotify);
+  
+  // nsIOptionElement
+  NS_IMETHOD SetSelectedInternal(PRBool aValue, PRBool aNotify);
+
+  // nsIContent
+  virtual PRInt32 IntrinsicState() const;
+
+  virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
+
+  nsresult CopyInnerTo(nsGenericElement* aDest) const;
+
+protected:
+  /**
+   * Get the select content element that contains this option, this
+   * intentionally does not return nsresult, all we care about is if
+   * there's a select associated with this option or not.
+   * @param aSelectElement the select element (out param)
+   */
+  nsIContent* GetSelect();
+
+  PRPackedBool mSelectedChanged;
+  PRPackedBool mIsSelected;
+
+  // True only while we're under the SetOptionsSelectedByIndex call when our
+  // "selected" attribute is changing and mSelectedChanged is false.
+  PRPackedBool mIsInSetDefaultSelected;
+};
+
+#endif
--- a/content/html/content/src/nsHTMLSelectElement.cpp
+++ b/content/html/content/src/nsHTMLSelectElement.cpp
@@ -33,16 +33,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * 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 "nsHTMLSelectElement.h"
+#include "nsHTMLOptionElement.h"
 #include "nsIDOMEventTarget.h"
 #include "nsContentCreatorFunctions.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsLayoutUtils.h"
 #include "nsMappedAttributes.h"
 #include "nsIForm.h"
 #include "nsFormSubmission.h"
@@ -64,16 +65,19 @@
 #include "nsIComboboxControlFrame.h"
 #include "nsIListControlFrame.h"
 #include "nsIFrame.h"
 
 #include "nsDOMError.h"
 #include "nsServiceManagerUtils.h"
 #include "nsRuleData.h"
 #include "nsEventDispatcher.h"
+#include "mozilla/dom/Element.h"
+
+using namespace mozilla::dom;
 
 NS_IMPL_ISUPPORTS1(nsSelectState, nsSelectState)
 NS_DEFINE_STATIC_IID_ACCESSOR(nsSelectState, NS_SELECT_STATE_IID)
 
 //----------------------------------------------------------------------
 //
 // nsSafeOptionListMutation
 //
@@ -346,17 +350,17 @@ nsHTMLSelectElement::InsertOptionsIntoLi
                                                   PRInt32* aInsertIndex,
                                                   PRInt32 aDepth)
 {
   // We *assume* here that someone's brain has not gone horribly
   // wrong by putting <option> inside of <option>.  I'm sorry, I'm
   // just not going to look for an option inside of an option.
   // Sue me.
 
-  nsCOMPtr<nsIDOMHTMLOptionElement> optElement(do_QueryInterface(aOptions));
+  nsHTMLOptionElement *optElement = nsHTMLOptionElement::FromContent(aOptions);
   if (optElement) {
     nsresult rv = mOptions->InsertOptionAt(optElement, *aInsertIndex);
     NS_ENSURE_SUCCESS(rv, rv);
     (*aInsertIndex)++;
     return NS_OK;
   }
 
   // If it's at the top level, then we just found out there are non-options
@@ -564,17 +568,17 @@ nsHTMLSelectElement::GetOptionIndexAfter
 
   return retval;
 }
 
 PRInt32
 nsHTMLSelectElement::GetFirstOptionIndex(nsIContent* aOptions)
 {
   PRInt32 listIndex = -1;
-  nsCOMPtr<nsIDOMHTMLOptionElement> optElement(do_QueryInterface(aOptions));
+  nsHTMLOptionElement *optElement = nsHTMLOptionElement::FromContent(aOptions);
   if (optElement) {
     GetOptionIndex(optElement, 0, PR_TRUE, &listIndex);
     // If you nested stuff under the option, you're just plain
     // screwed.  *I'm* not going to aid and abet your evil deed.
     return listIndex;
   }
 
   listIndex = GetFirstChildOptionIndex(aOptions, 0, aOptions->GetChildCount());
@@ -666,18 +670,17 @@ nsHTMLSelectElement::Remove(PRInt32 aInd
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLSelectElement::GetOptions(nsIDOMHTMLOptionsCollection** aValue)
 {
-  *aValue = mOptions;
-  NS_IF_ADDREF(*aValue);
+  NS_IF_ADDREF(*aValue = GetOptions());
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLSelectElement::GetType(nsAString& aType)
 {
   PRBool isMultiple;
@@ -790,17 +793,18 @@ nsHTMLSelectElement::SetSelectedIndex(PR
   return rv;
 }
 
 NS_IMETHODIMP
 nsHTMLSelectElement::GetOptionIndex(nsIDOMHTMLOptionElement* aOption,
                                     PRInt32 aStartIndex, PRBool aForward,
                                     PRInt32* aIndex)
 {
-  return mOptions->GetOptionIndex(aOption, aStartIndex, aForward, aIndex);
+  nsCOMPtr<Element> option = do_QueryInterface(aOption);
+  return mOptions->GetOptionIndex(option, aStartIndex, aForward, aIndex);
 }
 
 PRBool
 nsHTMLSelectElement::IsOptionSelectedByIndex(PRInt32 aIndex)
 {
   nsIDOMHTMLOptionElement *option = mOptions->ItemAsOption(aIndex);
   PRBool isSelected = PR_FALSE;
   if (option) {
@@ -1694,17 +1698,17 @@ void nsHTMLSelectElement::DispatchConten
   }
 }
 
 static void
 AddOptionsRecurse(nsIContent* aRoot, nsHTMLOptionCollection* aArray)
 {
   nsIContent* child;
   for(PRUint32 i = 0; (child = aRoot->GetChildAt(i)); ++i) {
-    nsCOMPtr<nsIDOMHTMLOptionElement> opt = do_QueryInterface(child);
+    nsHTMLOptionElement *opt = nsHTMLOptionElement::FromContent(child);
     if (opt) {
       // If we fail here, then at least we've tried our best
       aArray->AppendOption(opt);
     }
     else if (IsOptGroup(child)) {
       AddOptionsRecurse(child, aArray);
     }
   }
@@ -1767,17 +1771,17 @@ nsHTMLOptionCollection::~nsHTMLOptionCol
 void
 nsHTMLOptionCollection::DropReference()
 {
   // Drop our (non ref-counted) reference
   mSelect = nsnull;
 }
 
 nsresult
-nsHTMLOptionCollection::GetOptionIndex(nsIDOMHTMLOptionElement* aOption,
+nsHTMLOptionCollection::GetOptionIndex(mozilla::dom::Element* aOption,
                                        PRInt32 aStartIndex,
                                        PRBool aForward,
                                        PRInt32* aIndex)
 {
   PRInt32 index;
 
   // Make the common case fast
   if (aStartIndex == 0 && aForward) {
@@ -1785,36 +1789,42 @@ nsHTMLOptionCollection::GetOptionIndex(n
     if (index == -1) {
       return NS_ERROR_FAILURE;
     }
     
     *aIndex = index;
     return NS_OK;
   }
 
-  PRInt32 high = mElements.Count();
+  PRInt32 high = mElements.Length();
   PRInt32 step = aForward ? 1 : -1;
 
   for (index = aStartIndex; index < high && index > -1; index += step) {
     if (mElements[index] == aOption) {
       *aIndex = index;
       return NS_OK;
     }
   }
 
   return NS_ERROR_FAILURE;
 }
 
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLOptionCollection)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsHTMLOptionCollection)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mElements)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsHTMLOptionCollection)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mElements)
+    {
+      PRUint32 i;
+      for (i = 0; i < tmp->mElements.Length(); ++i) {
+        NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mElements[i]");
+        cb.NoteXPCOMChild(static_cast<Element*>(tmp->mElements[i]));
+      }
+    }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // nsISupports
 
 DOMCI_DATA(HTMLOptionsCollection, nsHTMLOptionCollection)
 
 // QueryInterface implementation for nsHTMLOptionCollection
 NS_INTERFACE_TABLE_HEAD(nsHTMLOptionCollection)
@@ -1834,17 +1844,17 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUO
                                            nsIHTMLCollection)
 
 
 // nsIDOMNSHTMLOptionCollection interface
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::GetLength(PRUint32* aLength)
 {
-  *aLength = mElements.Count();
+  *aLength = mElements.Length();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::SetLength(PRUint32 aLength)
 {
   if (!mSelect) {
@@ -1856,45 +1866,47 @@ nsHTMLOptionCollection::SetLength(PRUint
 
 NS_IMETHODIMP
 nsHTMLOptionCollection::SetOption(PRInt32 aIndex,
                                   nsIDOMHTMLOptionElement *aOption)
 {
   if (aIndex < 0 || !mSelect) {
     return NS_OK;
   }
-  
+
   // if the new option is null, just remove this option.  Note that it's safe
   // to pass a too-large aIndex in here.
   if (!aOption) {
     mSelect->Remove(aIndex);
 
     // We're done.
     return NS_OK;
   }
 
   nsresult rv = NS_OK;
 
+  PRUint32 index = PRUint32(aIndex);
+
   // Now we're going to be setting an option in our collection
-  if (aIndex > mElements.Count()) {
+  if (index > mElements.Length()) {
     // Fill our array with blank options up to (but not including, since we're
     // about to change it) aIndex, for compat with other browsers.
-    rv = SetLength(aIndex);
+    rv = SetLength(index);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  NS_ASSERTION(aIndex <= mElements.Count(), "SetLength lied");
+  NS_ASSERTION(index <= mElements.Length(), "SetLength lied");
   
   nsCOMPtr<nsIDOMNode> ret;
-  if (aIndex == mElements.Count()) {
+  if (index == mElements.Length()) {
     rv = mSelect->AppendChild(aOption, getter_AddRefs(ret));
   } else {
     // Find the option they're talking about and replace it
     // hold a strong reference to follow COM rules.
-    nsCOMPtr<nsIDOMHTMLOptionElement> refChild = mElements.SafeObjectAt(aIndex);
+    nsCOMPtr<nsIDOMHTMLOptionElement> refChild = ItemAsOption(index);
     NS_ENSURE_TRUE(refChild, NS_ERROR_UNEXPECTED);
 
     nsCOMPtr<nsIDOMNode> parent;
     refChild->GetParentNode(getter_AddRefs(parent));
     if (parent) {
       rv = parent->ReplaceChild(aOption, refChild, getter_AddRefs(ret));
     }
   }
@@ -1928,23 +1940,31 @@ nsHTMLOptionCollection::Item(PRUint32 aI
 
     return rv;
   }
 
   return CallQueryInterface(item, aReturn);
 }
 
 nsISupports*
+nsHTMLOptionCollection::GetNodeAt(PRUint32 aIndex, nsresult* aResult)
+{
+  *aResult = NS_OK;
+
+  return static_cast<Element*>(ItemAsOption(aIndex));
+}
+
+nsISupports*
 nsHTMLOptionCollection::GetNamedItem(const nsAString& aName, nsresult* aResult)
 {
   *aResult = NS_OK;
 
-  PRInt32 count = mElements.Count();
-  for (PRInt32 i = 0; i < count; i++) {
-    nsCOMPtr<nsIContent> content = do_QueryInterface(mElements.ObjectAt(i));
+  PRUint32 count = mElements.Length();
+  for (PRUint32 i = 0; i < count; i++) {
+    nsIContent *content = ItemAsOption(i);
     if (content &&
         (content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name, aName,
                               eCaseMatters) ||
          content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::id, aName,
                               eCaseMatters))) {
       return content;
     }
   }
--- a/content/html/content/src/nsHTMLSelectElement.h
+++ b/content/html/content/src/nsHTMLSelectElement.h
@@ -55,17 +55,17 @@
 #include "nsIHTMLCollection.h"
 
 // PresState
 #include "nsXPCOM.h"
 #include "nsPresState.h"
 #include "nsIComponentManager.h"
 #include "nsCheapSets.h"
 #include "nsLayoutErrors.h"
-
+#include "nsHTMLOptionElement.h"
 
 class nsHTMLSelectElement;
 
 /**
  * The collection of options in the select (what you get back when you do
  * select.options in DOM)
  */
 class nsHTMLOptionCollection: public nsIDOMHTMLOptionsCollection,
@@ -82,88 +82,83 @@ public:
   NS_DECL_NSIDOMHTMLOPTIONSCOLLECTION
 
   // nsIDOMNSHTMLOptionCollection interface
   NS_DECL_NSIDOMNSHTMLOPTIONCOLLECTION
 
   // nsIDOMHTMLCollection interface, all its methods are defined in
   // nsIDOMHTMLOptionsCollection
 
-  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult)
-  {
-    *aResult = NS_OK;
-
-    return mElements.SafeObjectAt(aIndex);
-  }
+  virtual nsISupports* GetNodeAt(PRUint32 aIndex, nsresult* aResult);
   virtual nsISupports* GetNamedItem(const nsAString& aName, nsresult* aResult);
 
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsHTMLOptionCollection,
                                            nsIHTMLCollection)
 
   // Helpers for nsHTMLSelectElement
   /**
    * Insert an option
    * @param aOption the option to insert
    * @param aIndex the index to insert at
    */
-  PRBool InsertOptionAt(nsIDOMHTMLOptionElement* aOption, PRInt32 aIndex)
+  PRBool InsertOptionAt(nsHTMLOptionElement* aOption, PRUint32 aIndex)
   {
-    return mElements.InsertObjectAt(aOption, aIndex);
+    return !!mElements.InsertElementAt(aIndex, aOption);
   }
 
   /**
    * Remove an option
    * @param aIndex the index of the option to remove
    */
-  void RemoveOptionAt(PRInt32 aIndex)
+  void RemoveOptionAt(PRUint32 aIndex)
   {
-    mElements.RemoveObjectAt(aIndex);
+    mElements.RemoveElementAt(aIndex);
   }
 
   /**
    * Get the option at the index
    * @param aIndex the index
    * @param aReturn the option returned [OUT]
    */
-  nsIDOMHTMLOptionElement *ItemAsOption(PRInt32 aIndex)
+  nsHTMLOptionElement *ItemAsOption(PRUint32 aIndex)
   {
-    return mElements.SafeObjectAt(aIndex);
+    return mElements.SafeElementAt(aIndex, nsRefPtr<nsHTMLOptionElement>());
   }
 
   /**
    * Clears out all options
    */
   void Clear()
   {
     mElements.Clear();
   }
 
   /**
    * Append an option to end of array
    */
-  PRBool AppendOption(nsIDOMHTMLOptionElement* aOption)
+  PRBool AppendOption(nsHTMLOptionElement* aOption)
   {
-    return mElements.AppendObject(aOption);
+    return !!mElements.AppendElement(aOption);
   }
 
   /**
    * Drop the reference to the select.  Called during select destruction.
    */
   void DropReference();
 
   /**
    * See nsISelectElement.idl for documentation on this method
    */
-  nsresult GetOptionIndex(nsIDOMHTMLOptionElement* aOption,
+  nsresult GetOptionIndex(mozilla::dom::Element* aOption,
                           PRInt32 aStartIndex, PRBool aForward,
                           PRInt32* aIndex);
 
 private:
   /** The list of options (holds strong references) */
-  nsCOMArray<nsIDOMHTMLOptionElement> mElements;
+  nsTArray<nsRefPtr<nsHTMLOptionElement> > mElements;
   /** The select element that contains this array */
   nsHTMLSelectElement* mSelect;
 };
 
 #define NS_SELECT_STATE_IID                        \
 { /* 4db54c7c-d159-455f-9d8e-f60ee466dbf3 */       \
   0x4db54c7c,                                      \
   0xd159,                                          \
@@ -304,16 +299,26 @@ public:
                                               PRInt32 aModType) const;
   NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
 
   virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(nsHTMLSelectElement,
                                                      nsGenericHTMLFormElement)
 
+  nsHTMLOptionCollection *GetOptions()
+  {
+    return mOptions;
+  }
+
+  static nsHTMLSelectElement *FromSupports(nsISupports *aSupports)
+  {
+    return static_cast<nsHTMLSelectElement*>(static_cast<nsINode*>(aSupports));
+  }
+
 protected:
   friend class nsSafeOptionListMutation;
 
   // Helper Methods
   /**
    * Check whether the option specified by the index is selected
    * @param aIndex the index
    * @return whether the option at the index is selected
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -209,17 +209,17 @@
 // includes needed for the prototype chain interfaces
 #include "nsIDOMNavigator.h"
 #include "nsIDOMBarProp.h"
 #include "nsIDOMScreen.h"
 #include "nsIDOMDocumentType.h"
 #include "nsIDOMDOMImplementation.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMDocumentEvent.h"
-#include "nsIDOMAttr.h"
+#include "nsDOMAttribute.h"
 #include "nsIDOMText.h"
 #include "nsIDOM3Text.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMCDATASection.h"
 #include "nsIDOMProcessingInstruction.h"
 #include "nsIDOMNotation.h"
 #include "nsIDOMNSEvent.h"
 #include "nsIDOMDataContainerEvent.h"
@@ -471,16 +471,18 @@
 // Simple gestures include
 #include "nsIDOMSimpleGestureEvent.h"
 
 #include "nsIDOMNSMouseEvent.h"
 
 #include "nsIEventListenerService.h"
 #include "nsIFrameMessageManager.h"
 #include "mozilla/dom/Element.h"
+#include "nsHTMLSelectElement.h"
+#include "nsHTMLLegendElement.h"
 
 using namespace mozilla::dom;
 
 #include "mozilla/dom/indexedDB/IDBFactory.h"
 #include "mozilla/dom/indexedDB/IDBRequest.h"
 #include "mozilla/dom/indexedDB/IDBDatabase.h"
 #include "mozilla/dom/indexedDB/IDBEvents.h"
 #include "mozilla/dom/indexedDB/IDBObjectStore.h"
@@ -7469,19 +7471,18 @@ nsNodeSH::PreCreate(nsISupports *nativeO
   // Event handling is possible only if (1). If (2) event handling is prevented.
   // If document has never had a script handling object,
   // untrusted scripts (3) shouldn't touch it!
   PRBool hasHadScriptHandlingObject = PR_FALSE;
   NS_ENSURE_STATE(doc->GetScriptHandlingObject(hasHadScriptHandlingObject) ||
                   hasHadScriptHandlingObject ||
                   IsPrivilegedScript());
 
-  nsISupports *native_parent;
-
-  PRBool slimWrappers = PR_TRUE;
+  nsINode *native_parent;
+
   PRBool nodeIsElement = node->IsElement();
   if (nodeIsElement && node->AsElement()->IsXUL()) {
     // For XUL elements, use the parent, if any.
     native_parent = node->GetParent();
 
     if (!native_parent) {
       native_parent = doc;
     }
@@ -7494,81 +7495,77 @@ nsNodeSH::PreCreate(nsISupports *nativeO
     native_parent = doc;
 
     // But for HTML form controls, use the form as scope parent.
     if (nodeIsElement) {
       if (node->IsNodeOfType(nsINode::eHTML_FORM_CONTROL)) {
         nsCOMPtr<nsIFormControl> form_control(do_QueryInterface(node));
 
         if (form_control) {
-          nsCOMPtr<nsIDOMHTMLFormElement> form;
-          form_control->GetForm(getter_AddRefs(form));
+          Element *form = form_control->GetFormElement();
 
           if (form) {
             // Found a form, use it.
             native_parent = form;
           }
         }
-      // Legend isn't an HTML form control but should have its fieldset form
-      // as scope parent at least for backward compatibility.
-      } else if (node->AsElement()->IsHTML() &&
-                 node->AsElement()->Tag() == nsGkAtoms::legend) {
-        nsCOMPtr<nsIDOMHTMLLegendElement> legend(do_QueryInterface(node));
-
+      }
+      else {
+        // Legend isn't an HTML form control but should have its fieldset form
+        // as scope parent at least for backward compatibility.
+        nsHTMLLegendElement *legend =
+          nsHTMLLegendElement::FromContent(node->AsElement());
         if (legend) {
-          nsCOMPtr<nsIDOMHTMLFormElement> form;
-          legend->GetForm(getter_AddRefs(form));
+          Element *form = legend->GetFormElement();
 
           if (form) {
             native_parent = form;
           }
         }
       }
     }
   } else {
     // We're called for a document object; set the parent to be the
     // document's global object, if there is one
 
     // Get the scope object from the document.
-    native_parent = doc->GetScopeObject();
-
-    if (!native_parent) {
+    nsISupports *scope = doc->GetScopeObject();
+
+    if (scope) {
+        jsval v;
+        nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
+        nsresult rv = WrapNative(cx, globalObj, scope, nsnull, PR_FALSE, &v,
+                                 getter_AddRefs(holder));
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        holder->GetJSObject(parentObj);
+    }
+    else {
       // No global object reachable from this document, use the
       // global object that was passed to this method.
 
       *parentObj = globalObj;
-
-      return node->IsInNativeAnonymousSubtree() ?
-        NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
-    }
-
-    slimWrappers = PR_FALSE;
+    }
+
+    // No slim wrappers for a document's scope object.
+    return node->IsInNativeAnonymousSubtree() ?
+      NS_SUCCESS_CHROME_ACCESS_ONLY : NS_OK;
   }
 
   // XXXjst: Maybe we need to find the global to use from the
   // nsIScriptGlobalObject that's reachable from the node we're about
   // to wrap here? But that's not always reachable, let's use
   // globalObj for now...
 
-  if (native_parent == doc && (*parentObj = doc->GetWrapper()))
-    return node->IsInNativeAnonymousSubtree() ?
-      NS_SUCCESS_CHROME_ACCESS_ONLY :
-      (slimWrappers ? NS_SUCCESS_ALLOW_SLIM_WRAPPERS : NS_OK);
-
-  jsval v;
-  nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
-  nsresult rv = WrapNative(cx, globalObj, native_parent, PR_FALSE, &v,
-                           getter_AddRefs(holder));
+  nsresult rv = WrapNativeParent(cx, globalObj, native_parent, native_parent,
+                                 parentObj);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  *parentObj = JSVAL_TO_OBJECT(v);
-
   return node->IsInNativeAnonymousSubtree() ?
-    NS_SUCCESS_CHROME_ACCESS_ONLY :
-    (slimWrappers ? NS_SUCCESS_ALLOW_SLIM_WRAPPERS : NS_OK);
+    NS_SUCCESS_CHROME_ACCESS_ONLY : NS_SUCCESS_ALLOW_SLIM_WRAPPERS;
 }
 
 NS_IMETHODIMP
 nsNodeSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                       JSObject *obj, jsval id, jsval *vp, PRBool *_retval)
 {
   nsNodeSH::PreserveWrapper(GetNative(wrapper, obj));
   return nsEventReceiverSH::AddProperty(wrapper, cx, obj, id, vp, _retval);
@@ -8356,26 +8353,28 @@ nsNamedArraySH::GetProperty(nsIXPConnect
 // NamedNodeMap helper
 
 nsISupports*
 nsNamedNodeMapSH::GetItemAt(nsISupports *aNative, PRUint32 aIndex,
                             nsresult *aResult)
 {
   nsDOMAttributeMap* map = nsDOMAttributeMap::FromSupports(aNative);
 
-  return map->GetItemAt(aIndex, aResult);
+  nsINode *attr = map->GetItemAt(aIndex, aResult);
+  return attr;
 }
 
 nsISupports*
 nsNamedNodeMapSH::GetNamedItem(nsISupports *aNative, const nsAString& aName,
                                nsresult *aResult)
 {
   nsDOMAttributeMap* map = nsDOMAttributeMap::FromSupports(aNative);
 
-  return map->GetNamedItem(aName, aResult);
+  nsINode *attr = map->GetNamedItem(aName, aResult);
+  return attr;
 }
 
 
 // HTMLCollection helper
 
 nsresult
 nsHTMLCollectionSH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                               JSObject *obj, PRUint32 *length)
@@ -9520,25 +9519,23 @@ NS_IMETHODIMP
 nsHTMLSelectElementSH::GetProperty(nsIXPConnectWrappedNative *wrapper,
                                    JSContext *cx, JSObject *obj, jsval id,
                                    jsval *vp, PRBool *_retval)
 {
   PRInt32 n = GetArrayIndexFromId(cx, id);
 
   nsresult rv = NS_OK;
   if (n >= 0) {
-    nsCOMPtr<nsIDOMHTMLSelectElement> s = do_QueryWrappedNative(wrapper, obj);
-
-    nsCOMPtr<nsIDOMHTMLOptionsCollection> options;
-    s->GetOptions(getter_AddRefs(options));
+    nsHTMLSelectElement *s =
+      nsHTMLSelectElement::FromSupports(GetNative(wrapper, obj));
+
+    nsHTMLOptionCollection *options = s->GetOptions();
 
     if (options) {
-      nsCOMPtr<nsIDOMNode> node;
-
-      options->Item(n, getter_AddRefs(node));
+      nsISupports *node = options->GetNodeAt(n, &rv);
 
       rv = WrapNative(cx, obj, node, &NS_GET_IID(nsIDOMNode), PR_TRUE, vp);
       if (NS_SUCCEEDED(rv)) {
         rv = NS_SUCCESS_I_DID_SOMETHING;
       }
       return rv;
     }
   }