Bug 685798 - Node.parentElement, r=bz
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Sun, 11 Sep 2011 15:45:39 -0700
changeset 76848 5eba835c23a7a214156a4545d90fc626d78d5ca2
parent 76847 b384cfab8b1d5bfabd2229c8f84717a5442e5bb1
child 76849 569a45bfb71c61e16a9c1f9162dd5355a7a374e2
push id340
push userclegnitto@mozilla.com
push dateTue, 08 Nov 2011 22:56:33 +0000
treeherdermozilla-esr52@c0983049bcaa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs685798
milestone9.0a1
Bug 685798 - Node.parentElement, r=bz
content/base/public/nsINode.h
content/base/src/nsDOMAttribute.cpp
content/base/src/nsDocument.cpp
content/base/src/nsGenericElement.cpp
content/base/test/test_bug685798.html
dom/interfaces/core/nsIDOMNode.idl
js/src/xpconnect/src/dom_quickstubs.qsconf
--- a/content/base/public/nsINode.h
+++ b/content/base/public/nsINode.h
@@ -50,16 +50,17 @@
 #include "nsDOMString.h"
 #include "jspubtd.h"
 #include "nsDOMMemoryReporter.h"
 
 class nsIContent;
 class nsIDocument;
 class nsIDOMEvent;
 class nsIDOMNode;
+class nsIDOMElement;
 class nsIDOMNodeList;
 class nsINodeList;
 class nsIPresShell;
 class nsEventChainVisitor;
 class nsEventChainPreVisitor;
 class nsEventChainPostVisitor;
 class nsEventListenerManager;
 class nsIPrincipal;
@@ -702,16 +703,25 @@ public:
    * Get the parent nsINode for this node. This can be either an nsIContent,
    * an nsIDocument or an nsIAttribute.
    * @return the parent node
    */
   nsINode* GetNodeParent() const
   {
     return mParent;
   }
+  
+  /**
+   * Get the parent nsINode for this node if it is an Element.
+   * @return the parent node
+   */
+  nsINode* GetElementParent() const
+  {
+    return mParent && mParent->IsElement() ? mParent : nsnull;
+  }
 
   /**
    * See nsIDOMEventTarget
    */
   NS_DECL_NSIDOMEVENTTARGET
   using nsIDOMEventTarget::AddEventListener;
 
   /**
@@ -1278,16 +1288,17 @@ protected:
 
 #ifdef DEBUG
   // Note: virtual so that IsInNativeAnonymousSubtree can be called accross
   // module boundaries.
   virtual void CheckNotNativeAnonymous() const;
 #endif
 
   nsresult GetParentNode(nsIDOMNode** aParentNode);
+  nsresult GetParentElement(nsIDOMElement** aParentElement);
   nsresult GetChildNodes(nsIDOMNodeList** aChildNodes);
   nsresult GetFirstChild(nsIDOMNode** aFirstChild);
   nsresult GetLastChild(nsIDOMNode** aLastChild);
   nsresult GetPreviousSibling(nsIDOMNode** aPrevSibling);
   nsresult GetNextSibling(nsIDOMNode** aNextSibling);
   nsresult GetOwnerDocument(nsIDOMDocument** aOwnerDocument);
 
   nsresult ReplaceOrInsertBefore(PRBool aReplace, nsIDOMNode *aNewChild,
--- a/content/base/src/nsDOMAttribute.cpp
+++ b/content/base/src/nsDOMAttribute.cpp
@@ -359,16 +359,23 @@ nsDOMAttribute::GetParentNode(nsIDOMNode
     document->WarnOnceAbout(nsIDocument::eParentNode);
   }
 
   *aParentNode = nsnull;
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDOMAttribute::GetParentElement(nsIDOMElement** aParentElement)
+{
+  *aParentElement = nsnull;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDOMAttribute::GetChildNodes(nsIDOMNodeList** aChildNodes)
 {
   nsIDocument* document = GetOwnerDoc();
   if (document) {
     document->WarnOnceAbout(nsIDocument::eChildNodes);
   }
 
   return nsINode::GetChildNodes(aChildNodes);
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -5665,16 +5665,23 @@ NS_IMETHODIMP
 nsDocument::GetParentNode(nsIDOMNode** aParentNode)
 {
   *aParentNode = nsnull;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsDocument::GetParentElement(nsIDOMElement** aParentElement)
+{
+  *aParentElement = nsnull;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 nsDocument::GetChildNodes(nsIDOMNodeList** aChildNodes)
 {
   return nsINode::GetChildNodes(aChildNodes);
 }
 
 NS_IMETHODIMP
 nsDocument::HasChildNodes(PRBool* aHasChildNodes)
 {
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -430,16 +430,24 @@ nsINode::GetParentNode(nsIDOMNode** aPar
   *aParentNode = nsnull;
 
   nsINode *parent = GetNodeParent();
 
   return parent ? CallQueryInterface(parent, aParentNode) : NS_OK;
 }
 
 nsresult
+nsINode::GetParentElement(nsIDOMElement** aParentElement)
+{
+  *aParentElement = nsnull;
+  nsINode* parent = GetElementParent();
+  return parent ? CallQueryInterface(parent, aParentElement) : NS_OK;
+}
+
+nsresult
 nsINode::GetChildNodes(nsIDOMNodeList** aChildNodes)
 {
   *aChildNodes = GetChildNodesList();
   if (!*aChildNodes) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
   NS_ADDREF(*aChildNodes);
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug685798.html
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=685798
+-->
+<head>
+  <title>Test for Bug 685798</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685798">Mozilla Bug 685798</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 685798 **/
+
+
+is(document.parentElement, null,
+   "Document shouldn't have parentElement.");
+is(document.documentElement.parentElement, null,
+   "DocumentElement shouldn't have parentElement.");
+is(document.documentElement.firstChild.parentElement, document.documentElement,
+   "DocumentElement's child should have DocumentElement as parent.");
+
+var df = document.createRange().createContextualFragment("<div>foo</div>");
+is(df.parentElement, null,
+   "DocumentFragment should be null.");
+is(df.firstChild.parentElement, null, 
+   "DocumentFragment's child shouldn't have parentElement");
+is(df.firstChild.firstChild.parentElement, df.firstChild,
+   "Text node's parent should be element.");
+
+is(document.createTextNode("foo").parentElement, null,
+   "Text node shouldn't have parent element.");
+
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/interfaces/core/nsIDOMNode.idl
+++ b/dom/interfaces/core/nsIDOMNode.idl
@@ -47,17 +47,17 @@ interface nsIDOMUserDataHandler;
  * The nsIDOMNode interface is the primary datatype for the entire 
  * Document Object Model.
  * It represents a single node in the document tree.
  *
  * For more information on this interface please see 
  * http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html
  */
 
-[scriptable, uuid(af9b19f7-7c88-4d16-9a3a-97390f824c58)]
+[scriptable, uuid(45e7ac3c-27d9-49bc-b3a3-dfc573f6f649)]
 interface nsIDOMNode : nsISupports
 {
   const unsigned short      ELEMENT_NODE       = 1;
   const unsigned short      ATTRIBUTE_NODE     = 2;
   const unsigned short      TEXT_NODE          = 3;
   const unsigned short      CDATA_SECTION_NODE = 4;
   const unsigned short      ENTITY_REFERENCE_NODE = 5;
   const unsigned short      ENTITY_NODE        = 6;
@@ -69,16 +69,17 @@ interface nsIDOMNode : nsISupports
   const unsigned short      NOTATION_NODE      = 12;
 
   readonly attribute DOMString        nodeName;
            attribute DOMString        nodeValue;
                                           // raises(DOMException) on setting
                                           // raises(DOMException) on retrieval
   readonly attribute unsigned short   nodeType;
   readonly attribute nsIDOMNode       parentNode;
+  readonly attribute nsIDOMElement    parentElement;
   readonly attribute nsIDOMNodeList   childNodes;
   readonly attribute nsIDOMNode       firstChild;
   readonly attribute nsIDOMNode       lastChild;
   readonly attribute nsIDOMNode       previousSibling;
   readonly attribute nsIDOMNode       nextSibling;
   readonly attribute nsIDOMNamedNodeMap attributes;
   // Modified in DOM Level 2:
   readonly attribute nsIDOMDocument   ownerDocument;
--- a/js/src/xpconnect/src/dom_quickstubs.qsconf
+++ b/js/src/xpconnect/src/dom_quickstubs.qsconf
@@ -592,16 +592,21 @@ customMethodCalls = {
         'code': '    nsIDocument *result = self->GetOwnerDocument();',
         'canFail': False
         },
     'nsIDOMNode_GetParentNode': {
         'thisType': 'nsINode',
         'code': '    nsINode *result = self->GetNodeParent();',
         'canFail': False
         },
+    'nsIDOMNode_GetParentElement': {
+        'thisType': 'nsINode',
+        'code': '    nsINode *result = self->GetElementParent();',
+        'canFail': False
+        },
     'nsIDOMNode_InsertBefore': {
         'thisType': 'nsINode',
         'arg0Type': 'nsINode',
         'arg1Type': 'nsINode',
         'code': '    nsINode *result = self->InsertBefore(arg0, arg1, &rv);\n'
                 '    if(NS_FAILED(rv))\n'
                 '        result = nsnull;'
         },