From 1d29441b127d7bafead61776067d5c480d7003c7 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Fri, 26 Apr 2013 08:48:23 +0200 Subject: [PATCH] Bug 852135 - Part c: Implement the remainder of the WebIDL API on nsDOMAttributeMap; r=bz --- content/base/src/Attr.cpp | 6 + content/base/src/Attr.h | 6 +- content/base/src/Element.cpp | 28 +---- content/base/src/nsDOMAttributeMap.cpp | 153 ++++++++++++++----------- content/base/src/nsDOMAttributeMap.h | 43 +++++-- 5 files changed, 132 insertions(+), 104 deletions(-) diff --git a/content/base/src/Attr.cpp b/content/base/src/Attr.cpp index d9a92663b793..ba258af71fd0 100644 --- a/content/base/src/Attr.cpp +++ b/content/base/src/Attr.cpp @@ -382,5 +382,11 @@ Attr::WrapObject(JSContext* aCx, JS::Handle aScope) return AttrBinding::Wrap(aCx, aScope, this); } +Element* +Attr::GetContentInternal() const +{ + return mAttrMap ? mAttrMap->GetContent() : nullptr; +} + } // namespace dom } // namespace mozilla diff --git a/content/base/src/Attr.h b/content/base/src/Attr.h index a947ec447acd..9fe42faa9daa 100644 --- a/content/base/src/Attr.h +++ b/content/base/src/Attr.h @@ -17,7 +17,6 @@ #include "nsString.h" #include "nsCOMPtr.h" #include "nsINodeInfo.h" -#include "nsDOMAttributeMap.h" #include "nsCycleCollectionParticipant.h" #include "nsStubMutationObserver.h" @@ -107,10 +106,7 @@ protected: private: already_AddRefed GetNameAtom(nsIContent* aContent); - mozilla::dom::Element *GetContentInternal() const - { - return mAttrMap ? mAttrMap->GetContent() : nullptr; - } + mozilla::dom::Element* GetContentInternal() const; nsString mValue; }; diff --git a/content/base/src/Element.cpp b/content/base/src/Element.cpp index 15978824f44b..1df4eff42bc0 100644 --- a/content/base/src/Element.cpp +++ b/content/base/src/Element.cpp @@ -790,14 +790,7 @@ Element::SetAttributeNode(Attr& aNewAttr, ErrorResult& aError) { OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNode); - nsCOMPtr attr; - aError = Attributes()->SetNamedItem(&aNewAttr, getter_AddRefs(attr)); - if (aError.Failed()) { - return nullptr; - } - - nsRefPtr returnAttr = static_cast(attr.get()); - return returnAttr.forget(); + return Attributes()->SetNamedItem(aNewAttr, aError); } already_AddRefed @@ -805,22 +798,7 @@ Element::RemoveAttributeNode(Attr& aAttribute, ErrorResult& aError) { OwnerDoc()->WarnOnceAbout(nsIDocument::eRemoveAttributeNode); - - nsAutoString name; - - aError = aAttribute.GetName(name); - if (aError.Failed()) { - return nullptr; - } - - nsCOMPtr attr; - aError = Attributes()->RemoveNamedItem(name, getter_AddRefs(attr)); - if (aError.Failed()) { - return nullptr; - } - - nsRefPtr returnAttr = static_cast(attr.get()); - return returnAttr.forget(); + return Attributes()->RemoveNamedItem(aAttribute.NodeName(), aError); } void @@ -904,7 +882,7 @@ Element::SetAttributeNodeNS(Attr& aNewAttr, ErrorResult& aError) { OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNodeNS); - return Attributes()->SetNamedItemNS(&aNewAttr, aError); + return Attributes()->SetNamedItemNS(aNewAttr, aError); } already_AddRefed diff --git a/content/base/src/nsDOMAttributeMap.cpp b/content/base/src/nsDOMAttributeMap.cpp index c9f4133aed69..66facdf12877 100644 --- a/content/base/src/nsDOMAttributeMap.cpp +++ b/content/base/src/nsDOMAttributeMap.cpp @@ -8,15 +8,16 @@ */ #include "nsDOMAttributeMap.h" + #include "mozilla/dom/Attr.h" -#include "nsIDOMDocument.h" #include "mozilla/dom/Element.h" -#include "nsIDocument.h" -#include "nsINameSpaceManager.h" -#include "nsError.h" -#include "nsContentUtils.h" -#include "nsNodeInfoManager.h" #include "nsAttrName.h" +#include "nsContentUtils.h" +#include "nsError.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsINameSpaceManager.h" +#include "nsNodeInfoManager.h" #include "nsUnicharUtils.h" using namespace mozilla; @@ -172,8 +173,9 @@ nsDOMAttributeMap::GetAttribute(nsINodeInfo* aNodeInfo, bool aNsAware) } Attr* -nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName) +nsDOMAttributeMap::NamedGetter(const nsAString& aAttrName, bool& aFound) { + aFound = false; NS_ENSURE_TRUE(mContent, nullptr); nsCOMPtr ni = mContent->GetExistingAttrNameFromQName(aAttrName); @@ -181,9 +183,17 @@ nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName) return nullptr; } + aFound = true; return GetAttribute(ni, false); } +Attr* +nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName) +{ + bool dummy; + return NamedGetter(aAttrName, dummy); +} + NS_IMETHODIMP nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName, nsIDOMAttr** aAttribute) @@ -198,21 +208,27 @@ nsDOMAttributeMap::GetNamedItem(const nsAString& aAttrName, NS_IMETHODIMP nsDOMAttributeMap::SetNamedItem(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn) { + Attr* attribute = static_cast(aAttr); + NS_ENSURE_ARG(attribute); + ErrorResult rv; - *aReturn = SetNamedItemInternal(aAttr, false, rv).get(); + *aReturn = SetNamedItem(*attribute, rv).get(); return rv.ErrorCode(); } NS_IMETHODIMP nsDOMAttributeMap::SetNamedItemNS(nsIDOMAttr* aAttr, nsIDOMAttr** aReturn) { + Attr* attribute = static_cast(aAttr); + NS_ENSURE_ARG(attribute); + ErrorResult rv; - *aReturn = SetNamedItemInternal(aAttr, true, rv).get(); + *aReturn = SetNamedItemNS(*attribute, rv).get(); return rv.ErrorCode(); } already_AddRefed -nsDOMAttributeMap::SetNamedItemInternal(nsIDOMAttr* aAttr, +nsDOMAttributeMap::SetNamedItemInternal(Attr& aAttr, bool aWithNS, ErrorResult& aError) { @@ -220,17 +236,9 @@ nsDOMAttributeMap::SetNamedItemInternal(nsIDOMAttr* aAttr, // XXX should check same-origin between mContent and aAttr however // nsContentUtils::CheckSameOrigin can't deal with attributenodes yet - - nsCOMPtr iAttribute(do_QueryInterface(aAttr)); - if (!iAttribute) { - aError.Throw(NS_ERROR_DOM_HIERARCHY_REQUEST_ERR); - return nullptr; - } - - Attr *attribute = static_cast(iAttribute.get()); // Check that attribute is not owned by somebody else - nsDOMAttributeMap* owner = iAttribute->GetMap(); + nsDOMAttributeMap* owner = aAttr.GetMap(); if (owner) { if (owner != this) { aError.Throw(NS_ERROR_DOM_INUSE_ATTRIBUTE_ERR); @@ -239,27 +247,19 @@ nsDOMAttributeMap::SetNamedItemInternal(nsIDOMAttr* aAttr, // setting a preexisting attribute is a no-op, just return the same // node. - NS_ADDREF(attribute); - return attribute; + nsRefPtr attribute = &aAttr; + return attribute.forget(); } nsresult rv; - if (!mContent->HasSameOwnerDoc(iAttribute)) { - nsCOMPtr domDoc = - do_QueryInterface(mContent->OwnerDoc(), &rv); - if (NS_FAILED(rv)) { - aError.Throw(rv); + if (!mContent->HasSameOwnerDoc(&aAttr)) { + nsCOMPtr adoptedNode = + mContent->OwnerDoc()->AdoptNode(aAttr, aError); + if (aError.Failed()) { return nullptr; } - nsCOMPtr adoptedNode; - rv = domDoc->AdoptNode(aAttr, getter_AddRefs(adoptedNode)); - if (NS_FAILED(rv)) { - aError.Throw(rv); - return nullptr; - } - - NS_ASSERTION(adoptedNode == aAttr, "Uh, adopt node changed nodes?"); + NS_ASSERTION(adoptedNode == &aAttr, "Uh, adopt node changed nodes?"); } // Get nodeinfo and preexisting attribute (if it exists) @@ -270,14 +270,13 @@ nsDOMAttributeMap::SetNamedItemInternal(nsIDOMAttr* aAttr, // SetNamedItemNS() if (aWithNS) { // Return existing attribute, if present - ni = iAttribute->NodeInfo(); + ni = aAttr.NodeInfo(); if (mContent->HasAttr(ni->NamespaceID(), ni->NameAtom())) { attr = RemoveAttribute(ni); } - } - else { // SetNamedItem() - attribute->GetName(name); + } else { // SetNamedItem() + aAttr.GetName(name); // get node-info of old attribute ni = mContent->GetExistingAttrNameFromQName(name); @@ -302,13 +301,13 @@ nsDOMAttributeMap::SetNamedItemInternal(nsIDOMAttr* aAttr, } nsAutoString value; - attribute->GetValue(value); + aAttr.GetValue(value); // Add the new attribute to the attribute map before updating // its value in the element. @see bug 364413. nsAttrKey attrkey(ni->NamespaceID(), ni->NameAtom()); - mAttributeCache.Put(attrkey, attribute); - iAttribute->SetMap(this); + mAttributeCache.Put(attrkey, &aAttr); + aAttr.SetMap(this); rv = mContent->SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(), value, true); @@ -325,57 +324,76 @@ nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName, nsIDOMAttr** aReturn) { NS_ENSURE_ARG_POINTER(aReturn); - *aReturn = nullptr; - NS_ENSURE_TRUE(mContent, NS_OK); + ErrorResult rv; + *aReturn = RemoveNamedItem(aName, rv).get(); + return rv.ErrorCode(); +} + +already_AddRefed +nsDOMAttributeMap::RemoveNamedItem(const nsAString& aName, ErrorResult& aError) +{ + NS_ENSURE_TRUE(mContent, nullptr); nsCOMPtr ni = mContent->GetExistingAttrNameFromQName(aName); if (!ni) { - return NS_ERROR_DOM_NOT_FOUND_ERR; + aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); + return nullptr; } - NS_ADDREF(*aReturn = GetAttribute(ni, true)); + nsRefPtr attribute = GetAttribute(ni, true); // This removes the attribute node from the attribute map. - return mContent->UnsetAttr(ni->NamespaceID(), ni->NameAtom(), true); + aError = mContent->UnsetAttr(ni->NamespaceID(), ni->NameAtom(), true); + return attribute.forget(); } Attr* -nsDOMAttributeMap::GetItemAt(uint32_t aIndex) +nsDOMAttributeMap::IndexedGetter(uint32_t aIndex, bool& aFound) { + aFound = false; NS_ENSURE_TRUE(mContent, nullptr); const nsAttrName* name = mContent->GetAttrNameAt(aIndex); NS_ENSURE_TRUE(name, nullptr); - // Don't use the nodeinfo even if one exists since it can - // have the wrong owner document. + aFound = true; + // Don't use the nodeinfo even if one exists since it can have the wrong + // owner document. nsCOMPtr ni = mContent->NodeInfo()->NodeInfoManager()-> GetNodeInfo(name->LocalName(), name->GetPrefix(), name->NamespaceID(), nsIDOMNode::ATTRIBUTE_NODE); return GetAttribute(ni, true); } +Attr* +nsDOMAttributeMap::Item(uint32_t aIndex) +{ + bool dummy; + return IndexedGetter(aIndex, dummy); +} + NS_IMETHODIMP nsDOMAttributeMap::Item(uint32_t aIndex, nsIDOMAttr** aReturn) { - NS_IF_ADDREF(*aReturn = GetItemAt(aIndex)); + NS_IF_ADDREF(*aReturn = Item(aIndex)); return NS_OK; } +uint32_t +nsDOMAttributeMap::Length() const +{ + NS_ENSURE_TRUE(mContent, 0); + + return mContent->GetAttrCount(); +} + nsresult nsDOMAttributeMap::GetLength(uint32_t *aLength) { NS_ENSURE_ARG_POINTER(aLength); - - if (mContent) { - *aLength = mContent->GetAttrCount(); - } - else { - *aLength = 0; - } - + *aLength = Length(); return NS_OK; } @@ -445,20 +463,27 @@ nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI, nsIDOMAttr** aReturn) { NS_ENSURE_ARG_POINTER(aReturn); - *aReturn = nullptr; + ErrorResult rv; + *aReturn = RemoveNamedItemNS(aNamespaceURI, aLocalName, rv).get(); + return rv.ErrorCode(); +} +already_AddRefed +nsDOMAttributeMap::RemoveNamedItemNS(const nsAString& aNamespaceURI, + const nsAString& aLocalName, + ErrorResult& aError) +{ nsCOMPtr ni = GetAttrNodeInfo(aNamespaceURI, aLocalName); - if (!ni) { - return NS_ERROR_DOM_NOT_FOUND_ERR; + aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR); + return nullptr; } nsRefPtr attr = RemoveAttribute(ni); - nsINodeInfo *attrNi = attr->NodeInfo(); + nsINodeInfo* attrNi = attr->NodeInfo(); mContent->UnsetAttr(attrNi->NamespaceID(), attrNi->NameAtom(), true); - attr.forget(aReturn); - return NS_OK; + return attr.forget(); } uint32_t diff --git a/content/base/src/nsDOMAttributeMap.h b/content/base/src/nsDOMAttributeMap.h index c4991c1fe150..8551dbd57079 100644 --- a/content/base/src/nsDOMAttributeMap.h +++ b/content/base/src/nsDOMAttributeMap.h @@ -10,12 +10,12 @@ #ifndef nsDOMAttributeMap_h #define nsDOMAttributeMap_h -#include "nsIDOMMozNamedAttrMap.h" -#include "nsStringGlue.h" -#include "nsRefPtrHashtable.h" -#include "nsCycleCollectionParticipant.h" -#include "nsIDOMAttr.h" +#include "mozilla/dom/Attr.h" #include "mozilla/ErrorResult.h" +#include "nsCycleCollectionParticipant.h" +#include "nsIDOMMozNamedAttrMap.h" +#include "nsRefPtrHashtable.h" +#include "nsStringGlue.h" class nsIAtom; class nsINodeInfo; @@ -23,7 +23,6 @@ class nsIDocument; namespace mozilla { namespace dom { -class Attr; class Element; } // namespace dom } // namespace mozilla @@ -140,8 +139,10 @@ public: */ uint32_t Enumerate(AttrCache::EnumReadFunction aFunc, void *aUserArg) const; - Attr* GetItemAt(uint32_t aIndex); - Attr* GetNamedItem(const nsAString& aAttrName); + Attr* GetItemAt(uint32_t aIndex) + { + return Item(aIndex); + } static nsDOMAttributeMap* FromSupports(nsISupports* aSupports) { @@ -162,15 +163,37 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap) + // WebIDL + Attr* GetNamedItem(const nsAString& aAttrName); + Attr* NamedGetter(const nsAString& aAttrName, bool& aFound); + already_AddRefed + SetNamedItem(Attr& aAttr, ErrorResult& aError) + { + return SetNamedItemInternal(aAttr, false, aError); + } + already_AddRefed + RemoveNamedItem(const nsAString& aName, ErrorResult& aError); + + Attr* Item(uint32_t aIndex); + Attr* IndexedGetter(uint32_t aIndex, bool& aFound); + uint32_t Length() const; + Attr* GetNamedItemNS(const nsAString& aNamespaceURI, const nsAString& aLocalName); - already_AddRefed SetNamedItemNS(Attr& aNode, ErrorResult& aError) { return SetNamedItemInternal(aNode, true, aError); } + already_AddRefed + RemoveNamedItemNS(const nsAString& aNamespaceURI, const nsAString& aLocalName, + ErrorResult& aError); + + void GetSupportedNames(nsTArray& aNames) + { + // No supported names we want to show up in iteration. + } size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const; @@ -187,7 +210,7 @@ private: * true) implementation. */ already_AddRefed - SetNamedItemInternal(nsIDOMAttr* aNode, bool aWithNS, ErrorResult& aError); + SetNamedItemInternal(Attr& aNode, bool aWithNS, ErrorResult& aError); already_AddRefed GetAttrNodeInfo(const nsAString& aNamespaceURI,