From dff32db5c4848ca1bbb900a5f063b3dfeb512a4c Mon Sep 17 00:00:00 2001 From: Peter Van der Beken Date: Mon, 19 Apr 2010 17:41:38 +0200 Subject: [PATCH] Fix for bug 560462 (Use fast unwrapping for more quickstubs) - add non-addrefing GetElementById and GetBody, add nsContentList-returning GetElementsByTagName(NS) and GetElementsByName. r=jst. --- content/base/src/nsDocument.cpp | 95 ++++++++++++++------ content/base/src/nsDocument.h | 9 ++ content/html/document/src/nsHTMLDocument.cpp | 56 ++++++------ content/html/document/src/nsHTMLDocument.h | 17 ++++ content/xul/document/src/nsXULDocument.cpp | 57 ++++++------ content/xul/document/src/nsXULDocument.h | 24 ++--- 6 files changed, 163 insertions(+), 95 deletions(-) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index d1edd0b31e64..2e8e66601c04 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -3914,26 +3914,47 @@ nsDocument::GetElementByIdInternal(nsIAtom* aID) return entry; } -NS_IMETHODIMP -nsDocument::GetElementById(const nsAString& aElementId, - nsIDOMElement** aReturn) +Element* +nsDocument::GetElementById(const nsAString& aElementId, nsresult *aResult) { - NS_ENSURE_ARG_POINTER(aReturn); - *aReturn = nsnull; - nsCOMPtr idAtom(do_GetAtom(aElementId)); - NS_ENSURE_TRUE(idAtom, NS_ERROR_OUT_OF_MEMORY); - if (!CheckGetElementByIdArg(idAtom)) - return NS_OK; + if (!idAtom) { + *aResult = NS_ERROR_OUT_OF_MEMORY; + + return nsnull; + } + + if (!CheckGetElementByIdArg(idAtom)) { + *aResult = NS_OK; + + return nsnull; + } nsIdentifierMapEntry *entry = GetElementByIdInternal(idAtom); - NS_ENSURE_TRUE(entry, NS_ERROR_OUT_OF_MEMORY); + if (!entry) { + *aResult = NS_ERROR_OUT_OF_MEMORY; - Element *e = entry->GetIdElement(); - if (!e) - return NS_OK; + return nsnull; + } - return CallQueryInterface(e, aReturn); + *aResult = NS_OK; + + return entry->GetIdElement(); +} + +NS_IMETHODIMP +nsDocument::GetElementById(const nsAString& aId, nsIDOMElement** aReturn) +{ + nsresult rv; + Element *content = GetElementById(aId, &rv); + if (content) { + rv = CallQueryInterface(content, aReturn); + } + else { + *aReturn = nsnull; + } + + return rv; } nsIContent* @@ -4385,25 +4406,38 @@ nsDocument::CreateEntityReference(const nsAString& aName, return NS_OK; } +already_AddRefed +nsDocument::GetElementsByTagName(const nsAString& aTagname) +{ + nsCOMPtr nameAtom = do_GetAtom(aTagname); + if (IsHTML()) { + nsAutoString tmp(aTagname); + ToLowerCase(tmp); // HTML elements are lower case internally. + nameAtom = do_GetAtom(tmp); + } + else { + nameAtom = do_GetAtom(aTagname); + } + NS_ENSURE_TRUE(nameAtom, nsnull); + + return NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown); +} + NS_IMETHODIMP nsDocument::GetElementsByTagName(const nsAString& aTagname, nsIDOMNodeList** aReturn) { - nsCOMPtr nameAtom = do_GetAtom(aTagname); - NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY); - - nsContentList *list = NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown).get(); + nsRefPtr list = GetElementsByTagName(aTagname); NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); // transfer ref to aReturn - *aReturn = list; + *aReturn = list.forget().get(); return NS_OK; } -NS_IMETHODIMP +already_AddRefed nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, - const nsAString& aLocalName, - nsIDOMNodeList** aReturn) + const nsAString& aLocalName) { PRInt32 nameSpaceId = kNameSpaceID_Wildcard; @@ -4411,17 +4445,26 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, nsresult rv = nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, nameSpaceId); - NS_ENSURE_SUCCESS(rv, rv); + NS_ENSURE_SUCCESS(rv, nsnull); } nsCOMPtr nameAtom = do_GetAtom(aLocalName); - NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY); + NS_ENSURE_TRUE(nameAtom, nsnull); - nsContentList *list = NS_GetContentList(this, nameAtom, nameSpaceId).get(); + return NS_GetContentList(this, nameAtom, nameSpaceId); +} + +NS_IMETHODIMP +nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, + const nsAString& aLocalName, + nsIDOMNodeList** aReturn) +{ + nsRefPtr list = GetElementsByTagNameNS(aNamespaceURI, + aLocalName); NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); // transfer ref to aReturn - *aReturn = list; + *aReturn = list.forget().get(); return NS_OK; } diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index e60ce08bff76..5c285f3b1831 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -930,6 +930,15 @@ public: // Only BlockOnload should call this! void AsyncBlockOnload(); + already_AddRefed + GetElementsByTagName(const nsAString& aTagName); + already_AddRefed + GetElementsByTagNameNS(const nsAString& aNamespaceURI, + const nsAString& aLocalName); + + virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId, + nsresult *aResult); + protected: friend class nsNodeUtils; void RegisterNamedItems(nsIContent *aContent); diff --git a/content/html/document/src/nsHTMLDocument.cpp b/content/html/document/src/nsHTMLDocument.cpp index 291dcdb10c70..fc5607468b6d 100644 --- a/content/html/document/src/nsHTMLDocument.cpp +++ b/content/html/document/src/nsHTMLDocument.cpp @@ -1389,11 +1389,7 @@ NS_IMETHODIMP nsHTMLDocument::GetElementsByTagName(const nsAString& aTagname, nsIDOMNodeList** aReturn) { - nsAutoString tmp(aTagname); - if (IsHTML()) { - ToLowerCase(tmp); // HTML elements are lower case internally. - } - return nsDocument::GetElementsByTagName(tmp, aReturn); + return nsDocument::GetElementsByTagName(aTagname, aReturn); } // nsIDOM3Document interface implementation @@ -1581,37 +1577,42 @@ nsHTMLDocument::GetURL(nsAString& aURL) return NS_OK; } -NS_IMETHODIMP -nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody) +nsIContent* +nsHTMLDocument::GetBody() { - *aBody = nsnull; - Element* body = GetBodyElement(); if (body) { // There is a body element, return that as the body. - return CallQueryInterface(body, aBody); + return body; } // The document is most likely a frameset document so look for the // outer most frameset element - nsCOMPtr nodeList; + nsRefPtr nodeList; - nsresult rv; if (IsHTML()) { - rv = GetElementsByTagName(NS_LITERAL_STRING("frameset"), - getter_AddRefs(nodeList)); + nodeList = nsDocument::GetElementsByTagName(NS_LITERAL_STRING("frameset")); } else { - rv = GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"), - NS_LITERAL_STRING("frameset"), - getter_AddRefs(nodeList)); + nodeList = + nsDocument::GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"), + NS_LITERAL_STRING("frameset")); } - NS_ENSURE_SUCCESS(rv, rv); - nsCOMPtr node; - nodeList->Item(0, getter_AddRefs(node)); + return nodeList ? nodeList->GetNodeAt(0) : nsnull; +} - return node ? CallQueryInterface(node, aBody) : NS_OK; +NS_IMETHODIMP +nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody) +{ + nsIContent *body = GetBody(); + if (!body) { + *aBody = nsnull; + + return NS_ERROR_OUT_OF_MEMORY; + } + + return CallQueryInterface(body, aBody); } NS_IMETHODIMP @@ -2287,18 +2288,11 @@ NS_IMETHODIMP nsHTMLDocument::GetElementsByName(const nsAString& aElementName, nsIDOMNodeList** aReturn) { - nsString* elementNameData = new nsString(aElementName); - NS_ENSURE_TRUE(elementNameData, NS_ERROR_OUT_OF_MEMORY); - nsContentList* elements = - NS_GetFuncStringContentList(this, - MatchNameAttribute, - nsContentUtils::DestroyMatchString, - elementNameData, - *elementNameData).get(); - NS_ENSURE_TRUE(elements, NS_ERROR_OUT_OF_MEMORY); + nsRefPtr list = GetElementsByName(aElementName); + NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); // Transfer ownership - *aReturn = elements; + list.forget(aReturn); return NS_OK; } diff --git a/content/html/document/src/nsHTMLDocument.h b/content/html/document/src/nsHTMLDocument.h index 4a98a01ef533..6aec5d4f7b5e 100644 --- a/content/html/document/src/nsHTMLDocument.h +++ b/content/html/document/src/nsHTMLDocument.h @@ -160,6 +160,17 @@ public: nsIDOMNodeList **_retval); virtual nsresult GetDocumentAllResult(const nsAString& aID, nsISupports** aResult); + nsIContent *GetBody(); + already_AddRefed GetElementsByName(const nsAString & aName) + { + nsString* elementNameData = new nsString(aName); + + return NS_GetFuncStringContentList(this, + MatchNameAttribute, + nsContentUtils::DestroyMatchString, + elementNameData, + *elementNameData); + } // nsIDOMNSHTMLDocument interface NS_DECL_NSIDOMNSHTMLDOCUMENT @@ -228,6 +239,12 @@ public: virtual NS_HIDDEN_(void) RemovedFromDocShell(); + virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId, + nsresult *aResult) + { + return nsDocument::GetElementById(aElementId, aResult); + } + protected: nsresult GetBodySize(PRInt32* aWidth, PRInt32* aHeight); diff --git a/content/xul/document/src/nsXULDocument.cpp b/content/xul/document/src/nsXULDocument.cpp index b786a38f6b5d..ea6e0f13e441 100644 --- a/content/xul/document/src/nsXULDocument.cpp +++ b/content/xul/document/src/nsXULDocument.cpp @@ -187,10 +187,10 @@ struct BroadcastListener { nsCOMPtr mAttribute; }; -nsIContent* -nsRefMapEntry::GetFirstContent() +Element* +nsRefMapEntry::GetFirstElement() { - return static_cast(mRefContentList.SafeElementAt(0)); + return static_cast(mRefContentList.SafeElementAt(0)); } void @@ -202,17 +202,17 @@ nsRefMapEntry::AppendAll(nsCOMArray* aElements) } PRBool -nsRefMapEntry::AddContent(nsIContent* aContent) +nsRefMapEntry::AddElement(Element* aElement) { - if (mRefContentList.IndexOf(aContent) >= 0) + if (mRefContentList.IndexOf(aElement) >= 0) return PR_TRUE; - return mRefContentList.AppendElement(aContent); + return mRefContentList.AppendElement(aElement); } PRBool -nsRefMapEntry::RemoveContent(nsIContent* aContent) +nsRefMapEntry::RemoveElement(Element* aElement) { - mRefContentList.RemoveElement(aContent); + mRefContentList.RemoveElement(aElement); return mRefContentList.Count() == 0; } @@ -978,7 +978,7 @@ nsXULDocument::AttributeWillChange(nsIDocument* aDocument, // See if we need to update our ref map. if (aAttribute == nsGkAtoms::ref || (aAttribute == nsGkAtoms::id && !aContent->GetIDAttributeName())) { - RemoveElementFromRefMap(aContent); + RemoveElementFromRefMap(aContent->AsElement()); } nsXMLDocument::AttributeWillChange(aDocument, aContent, aNameSpaceID, @@ -1323,7 +1323,7 @@ nsXULDocument::Persist(const nsAString& aID, nsresult rv; nsCOMPtr domelement; - rv = GetElementById(aID, getter_AddRefs(domelement)); + rv = nsDocument::GetElementById(aID, getter_AddRefs(domelement)); if (NS_FAILED(rv)) return rv; if (! domelement) @@ -1660,33 +1660,34 @@ nsXULDocument::GetCommandDispatcher(nsIDOMXULCommandDispatcher** aTracker) return NS_OK; } -NS_IMETHODIMP -nsXULDocument::GetElementById(const nsAString& aId, - nsIDOMElement** aReturn) +Element* +nsXULDocument::GetElementById(const nsAString& aId, nsresult *aResult) { - NS_ENSURE_ARG_POINTER(aReturn); - *aReturn = nsnull; + nsCOMPtr atom(do_GetAtom(aId)); + if (!atom) { + *aResult = NS_ERROR_OUT_OF_MEMORY; - nsCOMPtr atom = do_GetAtom(aId); - if (!atom) - return NS_ERROR_OUT_OF_MEMORY; + return nsnull; + } + + *aResult = NS_OK; if (!CheckGetElementByIdArg(atom)) - return NS_OK; + return nsnull; nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(atom); if (entry) { Element* element = entry->GetIdElement(); if (element) - return CallQueryInterface(element, aReturn); + return element; } nsRefMapEntry* refEntry = mRefMap.GetEntry(atom); if (refEntry) { - NS_ASSERTION(refEntry->GetFirstContent(), + NS_ASSERTION(refEntry->GetFirstElement(), "nsRefMapEntries should have nonempty content lists"); - return CallQueryInterface(refEntry->GetFirstContent(), aReturn); + return refEntry->GetFirstElement(); } - return NS_OK; + return nsnull; } nsresult @@ -1898,7 +1899,7 @@ nsXULDocument::GetTemplateBuilderFor(nsIContent* aContent, } static void -GetRefMapAttribute(nsIContent* aElement, nsAutoString* aValue) +GetRefMapAttribute(Element* aElement, nsAutoString* aValue) { aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::ref, *aValue); if (aValue->IsEmpty() && !aElement->GetIDAttributeName()) { @@ -1907,7 +1908,7 @@ GetRefMapAttribute(nsIContent* aElement, nsAutoString* aValue) } nsresult -nsXULDocument::AddElementToRefMap(nsIContent* aElement) +nsXULDocument::AddElementToRefMap(Element* aElement) { // Look at the element's 'ref' attribute, and if set, // add an entry in the resource-to-element map to the element. @@ -1920,7 +1921,7 @@ nsXULDocument::AddElementToRefMap(nsIContent* aElement) nsRefMapEntry *entry = mRefMap.PutEntry(atom); if (!entry) return NS_ERROR_OUT_OF_MEMORY; - if (!entry->AddContent(aElement)) + if (!entry->AddElement(aElement)) return NS_ERROR_OUT_OF_MEMORY; } @@ -1928,7 +1929,7 @@ nsXULDocument::AddElementToRefMap(nsIContent* aElement) } void -nsXULDocument::RemoveElementFromRefMap(nsIContent* aElement) +nsXULDocument::RemoveElementFromRefMap(Element* aElement) { // Remove the element from the resource-to-element map. nsAutoString value; @@ -1940,7 +1941,7 @@ nsXULDocument::RemoveElementFromRefMap(nsIContent* aElement) nsRefMapEntry *entry = mRefMap.GetEntry(atom); if (!entry) return; - if (entry->RemoveContent(aElement)) { + if (entry->RemoveElement(aElement)) { mRefMap.RemoveEntry(atom); } } diff --git a/content/xul/document/src/nsXULDocument.h b/content/xul/document/src/nsXULDocument.h index e7a9e6038acd..b5dd934c3625 100644 --- a/content/xul/document/src/nsXULDocument.h +++ b/content/xul/document/src/nsXULDocument.h @@ -90,17 +90,17 @@ public: NS_ERROR("Should never be called"); } - nsIContent* GetFirstContent(); + mozilla::dom::Element* GetFirstElement(); void AppendAll(nsCOMArray* aElements); /** - * @return true if aContent was added, false if we failed due to OOM + * @return true if aElement was added, false if we failed due to OOM */ - PRBool AddContent(nsIContent* aContent); + PRBool AddElement(mozilla::dom::Element* aElement); /** - * @return true if aContent was removed and it was the last content for + * @return true if aElement was removed and it was the last content for * this ref, so this entry should be removed from the map */ - PRBool RemoveContent(nsIContent* aContent); + PRBool RemoveElement(mozilla::dom::Element* aElement); private: nsSmallVoidArray mRefContentList; @@ -165,9 +165,13 @@ public: // nsIDOMNode interface overrides NS_IMETHOD CloneNode(PRBool deep, nsIDOMNode **_retval); - // nsIDOMDocument interface overrides - NS_IMETHOD GetElementById(const nsAString & elementId, - nsIDOMElement **_retval); + // nsDocument interface overrides + NS_IMETHOD GetElementById(const nsAString& aId, nsIDOMElement** aReturn) + { + return nsDocument::GetElementById(aId, aReturn); + } + virtual mozilla::dom::Element* GetElementById(const nsAString & elementId, + nsresult *aResult); // nsIDOMXULDocument interface NS_DECL_NSIDOMXULDOCUMENT @@ -207,9 +211,9 @@ protected: nsresult StartLayout(void); nsresult - AddElementToRefMap(nsIContent* aElement); + AddElementToRefMap(mozilla::dom::Element* aElement); void - RemoveElementFromRefMap(nsIContent* aElement); + RemoveElementFromRefMap(mozilla::dom::Element* aElement); nsresult GetViewportSize(PRInt32* aWidth, PRInt32* aHeight);