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;
}
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<nsIAtom> 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<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
nsDocument::GetElementsByTagName(const nsAString& aTagname,
nsIDOMNodeList** aReturn)
{
nsCOMPtr<nsIAtom> nameAtom = do_GetAtom(aTagname);
NS_ENSURE_TRUE(nameAtom, NS_ERROR_OUT_OF_MEMORY);
nsContentList *list = NS_GetContentList(this, nameAtom, kNameSpaceID_Unknown).get();
nsRefPtr<nsContentList> 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<nsContentList>
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<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);
// transfer ref to aReturn
*aReturn = list;
*aReturn = list.forget().get();
return NS_OK;
}

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

@ -930,6 +930,15 @@ public:
// Only BlockOnload should call this!
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:
friend class nsNodeUtils;
void RegisterNamedItems(nsIContent *aContent);

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

@ -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<nsIDOMNodeList> nodeList;
nsRefPtr<nsContentList> 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<nsIDOMNode> 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<nsContentList> list = GetElementsByName(aElementName);
NS_ENSURE_TRUE(list, NS_ERROR_OUT_OF_MEMORY);
// Transfer ownership
*aReturn = elements;
list.forget(aReturn);
return NS_OK;
}

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

@ -160,6 +160,17 @@ public:
nsIDOMNodeList **_retval);
virtual nsresult GetDocumentAllResult(const nsAString& aID,
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
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);

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

@ -187,10 +187,10 @@ struct BroadcastListener {
nsCOMPtr<nsIAtom> mAttribute;
};
nsIContent*
nsRefMapEntry::GetFirstContent()
Element*
nsRefMapEntry::GetFirstElement()
{
return static_cast<nsIContent*>(mRefContentList.SafeElementAt(0));
return static_cast<Element*>(mRefContentList.SafeElementAt(0));
}
void
@ -202,17 +202,17 @@ nsRefMapEntry::AppendAll(nsCOMArray<nsIContent>* 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<nsIDOMElement> 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<nsIAtom> atom(do_GetAtom(aId));
if (!atom) {
*aResult = NS_ERROR_OUT_OF_MEMORY;
nsCOMPtr<nsIAtom> 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);
}
}

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

@ -90,17 +90,17 @@ public:
NS_ERROR("Should never be called");
}
nsIContent* GetFirstContent();
mozilla::dom::Element* GetFirstElement();
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
*/
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);