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.

This commit is contained in:
Peter Van der Beken 2010-04-19 17:41:38 +02:00
Родитель 86ecf361a5
Коммит dff32db5c4
6 изменённых файлов: 163 добавлений и 95 удалений

Просмотреть файл

@ -3914,26 +3914,47 @@ nsDocument::GetElementByIdInternal(nsIAtom* aID)
return entry; return entry;
} }
NS_IMETHODIMP Element*
nsDocument::GetElementById(const nsAString& aElementId, nsDocument::GetElementById(const nsAString& aElementId, nsresult *aResult)
nsIDOMElement** aReturn)
{ {
NS_ENSURE_ARG_POINTER(aReturn);
*aReturn = nsnull;
nsCOMPtr<nsIAtom> idAtom(do_GetAtom(aElementId)); nsCOMPtr<nsIAtom> idAtom(do_GetAtom(aElementId));
NS_ENSURE_TRUE(idAtom, NS_ERROR_OUT_OF_MEMORY); if (!idAtom) {
if (!CheckGetElementByIdArg(idAtom)) *aResult = NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
return nsnull;
}
if (!CheckGetElementByIdArg(idAtom)) {
*aResult = NS_OK;
return nsnull;
}
nsIdentifierMapEntry *entry = GetElementByIdInternal(idAtom); 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(); return nsnull;
if (!e) }
return NS_OK;
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* nsIContent*
@ -4385,25 +4406,38 @@ nsDocument::CreateEntityReference(const nsAString& aName,
return NS_OK; return NS_OK;
} }
already_AddRefed<nsContentList>
nsDocument::GetElementsByTagName(const nsAString& aTagname)
{
nsCOMPtr<nsIAtom> 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 NS_IMETHODIMP
nsDocument::GetElementsByTagName(const nsAString& aTagname, nsDocument::GetElementsByTagName(const nsAString& aTagname,
nsIDOMNodeList** aReturn) nsIDOMNodeList** aReturn)
{ {
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aTagname); nsRefPtr<nsContentList> list = GetElementsByTagName(aTagname);
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
nsContentList *list = NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown).get();
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
// transfer ref to aReturn // transfer ref to aReturn
*aReturn = list; *aReturn = list.forget().get();
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP already_AddRefed<nsContentList>
nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI, nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName, const nsAString& aLocalName)
nsIDOMNodeList** aReturn)
{ {
PRInt32 nameSpaceId = kNameSpaceID_Wildcard; PRInt32 nameSpaceId = kNameSpaceID_Wildcard;
@ -4411,17 +4445,26 @@ nsDocument::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
nsresult rv = nsresult rv =
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI, nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
nameSpaceId); nameSpaceId);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, nsnull);
} }
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aLocalName); nsCOMPtr<nsIAtom> 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<nsContentList> list = GetElementsByTagNameNS(aNamespaceURI,
aLocalName);
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
// transfer ref to aReturn // transfer ref to aReturn
*aReturn = list; *aReturn = list.forget().get();
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -930,6 +930,15 @@ public:
// Only BlockOnload should call this! // Only BlockOnload should call this!
void AsyncBlockOnload(); void AsyncBlockOnload();
already_AddRefed<nsContentList>
GetElementsByTagName(const nsAString& aTagName);
already_AddRefed<nsContentList>
GetElementsByTagNameNS(const nsAString& aNamespaceURI,
const nsAString& aLocalName);
virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId,
nsresult *aResult);
protected: protected:
friend class nsNodeUtils; friend class nsNodeUtils;
void RegisterNamedItems(nsIContent *aContent); void RegisterNamedItems(nsIContent *aContent);

Просмотреть файл

@ -1389,11 +1389,7 @@ NS_IMETHODIMP
nsHTMLDocument::GetElementsByTagName(const nsAString& aTagname, nsHTMLDocument::GetElementsByTagName(const nsAString& aTagname,
nsIDOMNodeList** aReturn) nsIDOMNodeList** aReturn)
{ {
nsAutoString tmp(aTagname); return nsDocument::GetElementsByTagName(aTagname, aReturn);
if (IsHTML()) {
ToLowerCase(tmp); // HTML elements are lower case internally.
}
return nsDocument::GetElementsByTagName(tmp, aReturn);
} }
// nsIDOM3Document interface implementation // nsIDOM3Document interface implementation
@ -1581,37 +1577,42 @@ nsHTMLDocument::GetURL(nsAString& aURL)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP nsIContent*
nsHTMLDocument::GetBody(nsIDOMHTMLElement** aBody) nsHTMLDocument::GetBody()
{ {
*aBody = nsnull;
Element* body = GetBodyElement(); Element* body = GetBodyElement();
if (body) { if (body) {
// There is a body element, return that as the 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 // The document is most likely a frameset document so look for the
// outer most frameset element // outer most frameset element
nsCOMPtr<nsIDOMNodeList> nodeList; nsRefPtr<nsContentList> nodeList;
nsresult rv;
if (IsHTML()) { if (IsHTML()) {
rv = GetElementsByTagName(NS_LITERAL_STRING("frameset"), nodeList = nsDocument::GetElementsByTagName(NS_LITERAL_STRING("frameset"));
getter_AddRefs(nodeList));
} else { } else {
rv = GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"), nodeList =
NS_LITERAL_STRING("frameset"), nsDocument::GetElementsByTagNameNS(NS_LITERAL_STRING("http://www.w3.org/1999/xhtml"),
getter_AddRefs(nodeList)); NS_LITERAL_STRING("frameset"));
} }
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMNode> node; return nodeList ? nodeList->GetNodeAt(0) : nsnull;
nodeList->Item(0, getter_AddRefs(node)); }
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 NS_IMETHODIMP
@ -2287,18 +2288,11 @@ NS_IMETHODIMP
nsHTMLDocument::GetElementsByName(const nsAString& aElementName, nsHTMLDocument::GetElementsByName(const nsAString& aElementName,
nsIDOMNodeList** aReturn) nsIDOMNodeList** aReturn)
{ {
nsString* elementNameData = new nsString(aElementName); nsRefPtr<nsContentList> list = GetElementsByName(aElementName);
NS_ENSURE_TRUE(elementNameData, NS_ERROR_OUT_OF_MEMORY); NS_ENSURE_TRUE(list, 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);
// Transfer ownership // Transfer ownership
*aReturn = elements; list.forget(aReturn);
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -160,6 +160,17 @@ public:
nsIDOMNodeList **_retval); nsIDOMNodeList **_retval);
virtual nsresult GetDocumentAllResult(const nsAString& aID, virtual nsresult GetDocumentAllResult(const nsAString& aID,
nsISupports** aResult); nsISupports** aResult);
nsIContent *GetBody();
already_AddRefed<nsContentList> GetElementsByName(const nsAString & aName)
{
nsString* elementNameData = new nsString(aName);
return NS_GetFuncStringContentList(this,
MatchNameAttribute,
nsContentUtils::DestroyMatchString,
elementNameData,
*elementNameData);
}
// nsIDOMNSHTMLDocument interface // nsIDOMNSHTMLDocument interface
NS_DECL_NSIDOMNSHTMLDOCUMENT NS_DECL_NSIDOMNSHTMLDOCUMENT
@ -228,6 +239,12 @@ public:
virtual NS_HIDDEN_(void) RemovedFromDocShell(); virtual NS_HIDDEN_(void) RemovedFromDocShell();
virtual mozilla::dom::Element *GetElementById(const nsAString& aElementId,
nsresult *aResult)
{
return nsDocument::GetElementById(aElementId, aResult);
}
protected: protected:
nsresult GetBodySize(PRInt32* aWidth, nsresult GetBodySize(PRInt32* aWidth,
PRInt32* aHeight); PRInt32* aHeight);

Просмотреть файл

@ -187,10 +187,10 @@ struct BroadcastListener {
nsCOMPtr<nsIAtom> mAttribute; nsCOMPtr<nsIAtom> mAttribute;
}; };
nsIContent* Element*
nsRefMapEntry::GetFirstContent() nsRefMapEntry::GetFirstElement()
{ {
return static_cast<nsIContent*>(mRefContentList.SafeElementAt(0)); return static_cast<Element*>(mRefContentList.SafeElementAt(0));
} }
void void
@ -202,17 +202,17 @@ nsRefMapEntry::AppendAll(nsCOMArray<nsIContent>* aElements)
} }
PRBool PRBool
nsRefMapEntry::AddContent(nsIContent* aContent) nsRefMapEntry::AddElement(Element* aElement)
{ {
if (mRefContentList.IndexOf(aContent) >= 0) if (mRefContentList.IndexOf(aElement) >= 0)
return PR_TRUE; return PR_TRUE;
return mRefContentList.AppendElement(aContent); return mRefContentList.AppendElement(aElement);
} }
PRBool PRBool
nsRefMapEntry::RemoveContent(nsIContent* aContent) nsRefMapEntry::RemoveElement(Element* aElement)
{ {
mRefContentList.RemoveElement(aContent); mRefContentList.RemoveElement(aElement);
return mRefContentList.Count() == 0; return mRefContentList.Count() == 0;
} }
@ -978,7 +978,7 @@ nsXULDocument::AttributeWillChange(nsIDocument* aDocument,
// See if we need to update our ref map. // See if we need to update our ref map.
if (aAttribute == nsGkAtoms::ref || if (aAttribute == nsGkAtoms::ref ||
(aAttribute == nsGkAtoms::id && !aContent->GetIDAttributeName())) { (aAttribute == nsGkAtoms::id && !aContent->GetIDAttributeName())) {
RemoveElementFromRefMap(aContent); RemoveElementFromRefMap(aContent->AsElement());
} }
nsXMLDocument::AttributeWillChange(aDocument, aContent, aNameSpaceID, nsXMLDocument::AttributeWillChange(aDocument, aContent, aNameSpaceID,
@ -1323,7 +1323,7 @@ nsXULDocument::Persist(const nsAString& aID,
nsresult rv; nsresult rv;
nsCOMPtr<nsIDOMElement> domelement; nsCOMPtr<nsIDOMElement> domelement;
rv = GetElementById(aID, getter_AddRefs(domelement)); rv = nsDocument::GetElementById(aID, getter_AddRefs(domelement));
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
if (! domelement) if (! domelement)
@ -1660,33 +1660,34 @@ nsXULDocument::GetCommandDispatcher(nsIDOMXULCommandDispatcher** aTracker)
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP Element*
nsXULDocument::GetElementById(const nsAString& aId, nsXULDocument::GetElementById(const nsAString& aId, nsresult *aResult)
nsIDOMElement** aReturn)
{ {
NS_ENSURE_ARG_POINTER(aReturn); nsCOMPtr<nsIAtom> atom(do_GetAtom(aId));
*aReturn = nsnull; if (!atom) {
*aResult = NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIAtom> atom = do_GetAtom(aId); return nsnull;
if (!atom) }
return NS_ERROR_OUT_OF_MEMORY;
*aResult = NS_OK;
if (!CheckGetElementByIdArg(atom)) if (!CheckGetElementByIdArg(atom))
return NS_OK; return nsnull;
nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(atom); nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(atom);
if (entry) { if (entry) {
Element* element = entry->GetIdElement(); Element* element = entry->GetIdElement();
if (element) if (element)
return CallQueryInterface(element, aReturn); return element;
} }
nsRefMapEntry* refEntry = mRefMap.GetEntry(atom); nsRefMapEntry* refEntry = mRefMap.GetEntry(atom);
if (refEntry) { if (refEntry) {
NS_ASSERTION(refEntry->GetFirstContent(), NS_ASSERTION(refEntry->GetFirstElement(),
"nsRefMapEntries should have nonempty content lists"); "nsRefMapEntries should have nonempty content lists");
return CallQueryInterface(refEntry->GetFirstContent(), aReturn); return refEntry->GetFirstElement();
} }
return NS_OK; return nsnull;
} }
nsresult nsresult
@ -1898,7 +1899,7 @@ nsXULDocument::GetTemplateBuilderFor(nsIContent* aContent,
} }
static void static void
GetRefMapAttribute(nsIContent* aElement, nsAutoString* aValue) GetRefMapAttribute(Element* aElement, nsAutoString* aValue)
{ {
aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::ref, *aValue); aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::ref, *aValue);
if (aValue->IsEmpty() && !aElement->GetIDAttributeName()) { if (aValue->IsEmpty() && !aElement->GetIDAttributeName()) {
@ -1907,7 +1908,7 @@ GetRefMapAttribute(nsIContent* aElement, nsAutoString* aValue)
} }
nsresult nsresult
nsXULDocument::AddElementToRefMap(nsIContent* aElement) nsXULDocument::AddElementToRefMap(Element* aElement)
{ {
// Look at the element's 'ref' attribute, and if set, // Look at the element's 'ref' attribute, and if set,
// add an entry in the resource-to-element map to the element. // 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); nsRefMapEntry *entry = mRefMap.PutEntry(atom);
if (!entry) if (!entry)
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
if (!entry->AddContent(aElement)) if (!entry->AddElement(aElement))
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
@ -1928,7 +1929,7 @@ nsXULDocument::AddElementToRefMap(nsIContent* aElement)
} }
void void
nsXULDocument::RemoveElementFromRefMap(nsIContent* aElement) nsXULDocument::RemoveElementFromRefMap(Element* aElement)
{ {
// Remove the element from the resource-to-element map. // Remove the element from the resource-to-element map.
nsAutoString value; nsAutoString value;
@ -1940,7 +1941,7 @@ nsXULDocument::RemoveElementFromRefMap(nsIContent* aElement)
nsRefMapEntry *entry = mRefMap.GetEntry(atom); nsRefMapEntry *entry = mRefMap.GetEntry(atom);
if (!entry) if (!entry)
return; return;
if (entry->RemoveContent(aElement)) { if (entry->RemoveElement(aElement)) {
mRefMap.RemoveEntry(atom); mRefMap.RemoveEntry(atom);
} }
} }

Просмотреть файл

@ -90,17 +90,17 @@ public:
NS_ERROR("Should never be called"); NS_ERROR("Should never be called");
} }
nsIContent* GetFirstContent(); mozilla::dom::Element* GetFirstElement();
void AppendAll(nsCOMArray<nsIContent>* aElements); void AppendAll(nsCOMArray<nsIContent>* 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 * this ref, so this entry should be removed from the map
*/ */
PRBool RemoveContent(nsIContent* aContent); PRBool RemoveElement(mozilla::dom::Element* aElement);
private: private:
nsSmallVoidArray mRefContentList; nsSmallVoidArray mRefContentList;
@ -165,9 +165,13 @@ public:
// nsIDOMNode interface overrides // nsIDOMNode interface overrides
NS_IMETHOD CloneNode(PRBool deep, nsIDOMNode **_retval); NS_IMETHOD CloneNode(PRBool deep, nsIDOMNode **_retval);
// nsIDOMDocument interface overrides // nsDocument interface overrides
NS_IMETHOD GetElementById(const nsAString & elementId, NS_IMETHOD GetElementById(const nsAString& aId, nsIDOMElement** aReturn)
nsIDOMElement **_retval); {
return nsDocument::GetElementById(aId, aReturn);
}
virtual mozilla::dom::Element* GetElementById(const nsAString & elementId,
nsresult *aResult);
// nsIDOMXULDocument interface // nsIDOMXULDocument interface
NS_DECL_NSIDOMXULDOCUMENT NS_DECL_NSIDOMXULDOCUMENT
@ -207,9 +211,9 @@ protected:
nsresult StartLayout(void); nsresult StartLayout(void);
nsresult nsresult
AddElementToRefMap(nsIContent* aElement); AddElementToRefMap(mozilla::dom::Element* aElement);
void void
RemoveElementFromRefMap(nsIContent* aElement); RemoveElementFromRefMap(mozilla::dom::Element* aElement);
nsresult GetViewportSize(PRInt32* aWidth, PRInt32* aHeight); nsresult GetViewportSize(PRInt32* aWidth, PRInt32* aHeight);