Bug 685798 - Node.parentElement, r=bz
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Sun, 11 Sep 2011 15:45:39 -0700
changeset 77918 5eba835c23a7a214156a4545d90fc626d78d5ca2
parent 77917 b384cfab8b1d5bfabd2229c8f84717a5442e5bb1
child 77919 569a45bfb71c61e16a9c1f9162dd5355a7a374e2
push id340
push userclegnitto@mozilla.com
push dateTue, 08 Nov 2011 22:56:33 +0000
treeherdermozilla-beta@f745dc151615 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs685798
milestone9.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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;'
         },