diff options
Diffstat (limited to 'dom')
-rw-r--r-- | dom/base/nsINode.cpp | 25 | ||||
-rw-r--r-- | dom/base/nsINode.h | 10 | ||||
-rw-r--r-- | dom/tests/mochitest/webcomponents/mochitest.ini | 1 | ||||
-rw-r--r-- | dom/tests/mochitest/webcomponents/test_bug1269155.html | 89 | ||||
-rw-r--r-- | dom/webidl/Node.webidl | 9 |
5 files changed, 128 insertions, 6 deletions
diff --git a/dom/base/nsINode.cpp b/dom/base/nsINode.cpp index 212110b72..355bf0ebf 100644 --- a/dom/base/nsINode.cpp +++ b/dom/base/nsINode.cpp @@ -107,6 +107,7 @@ #include "GeometryUtils.h" #include "nsIAnimationObserver.h" #include "nsChildContentList.h" +#include "mozilla/dom/NodeBinding.h" #ifdef ACCESSIBILITY #include "mozilla/dom/AccessibleNode.h" @@ -250,6 +251,30 @@ nsINode::GetTextEditorRootContent(nsIEditor** aEditor) return nullptr; } +nsINode* nsINode::GetRootNode(const GetRootNodeOptions& aOptions) +{ + if (aOptions.mComposed) { + if (IsInComposedDoc() && GetComposedDoc()) { + return OwnerDoc(); + } + + nsINode* node = this; + ShadowRoot* shadowRootParent = nullptr; + while(node) { + node = node->SubtreeRoot(); + shadowRootParent = ShadowRoot::FromNode(node); + if (!shadowRootParent) { + break; + } + node = shadowRootParent->GetHost(); + } + + return node; + } + + return SubtreeRoot(); +} + nsINode* nsINode::SubtreeRoot() const { diff --git a/dom/base/nsINode.h b/dom/base/nsINode.h index d82f5f899..43d44db60 100644 --- a/dom/base/nsINode.h +++ b/dom/base/nsINode.h @@ -83,6 +83,7 @@ template<typename> class Sequence; class Text; class TextOrElementOrDocument; struct DOMPointInit; +struct GetRootNodeOptions; } // namespace dom } // namespace mozilla @@ -942,10 +943,11 @@ public: */ nsINode* SubtreeRoot() const; - nsINode* RootNode() const - { - return SubtreeRoot(); - } + /* + * Get context object's shadow-including root if options's composed is true, + * and context object's root otherwise. + */ + nsINode* GetRootNode(const mozilla::dom::GetRootNodeOptions& aOptions); /** * See nsIDOMEventTarget diff --git a/dom/tests/mochitest/webcomponents/mochitest.ini b/dom/tests/mochitest/webcomponents/mochitest.ini index 496f7ea4d..f05140c57 100644 --- a/dom/tests/mochitest/webcomponents/mochitest.ini +++ b/dom/tests/mochitest/webcomponents/mochitest.ini @@ -46,3 +46,4 @@ support-files = [test_style_fallback_content.html] [test_unresolved_pseudo_class.html] [test_link_prefetch.html] +[test_bug1269155.html] diff --git a/dom/tests/mochitest/webcomponents/test_bug1269155.html b/dom/tests/mochitest/webcomponents/test_bug1269155.html new file mode 100644 index 000000000..f280ae1d2 --- /dev/null +++ b/dom/tests/mochitest/webcomponents/test_bug1269155.html @@ -0,0 +1,89 @@ +<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1269155
+-->
+<head>
+ <title>Test for Bug 1269155</title>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+ <script type="text/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=1269155">Mozilla Bug 1269155</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+/** Test for Bug 1269155 **/
+var host = document.querySelector('#content');
+ var root = host.createShadowRoot();
+
+ var header1 = document.createElement('h1');
+ header1.textContent = 'Shadow Header1';
+
+ var paragraph1 = document.createElement('p');
+ paragraph1.textContent = 'shadow text paragraph1';
+
+ root.appendChild(header1);
+ root.appendChild(paragraph1);
+
+var root2 = paragraph1.createShadowRoot();
+var header2 = document.createElement('h2');
+header2.textContent = 'Shadow Header2';
+
+var paragraph2 = document.createElement('p');
+paragraph2.textContent = 'shadow text paragraph2';
+root2.appendChild(header2);
+root2.appendChild(paragraph2);
+
+
+var frag = document.createDocumentFragment();
+var paragraph3 = document.createElement('p');
+paragraph3.textContent = 'fragment paragraph3';
+frag.appendChild(paragraph3);
+
+var root3 = paragraph3.createShadowRoot();
+var header4 = document.createElement('h2');
+header4.textContent = 'Shadow Header3';
+
+var paragraph4 = document.createElement('p');
+paragraph4.textContent = 'shadow text paragraph4';
+
+root3.appendChild(header4);
+root3.appendChild(paragraph4);
+
+//shadow dom without compose
+is(root.getRootNode(), root, "root.getRootNode() should be root.");
+is(root2.getRootNode(), root2, "root2.getRootNode() should be root.");
+is(root3.getRootNode(), root3, "root3.getRootNode() should be root.");
+is(header1.getRootNode(), root, "header1.getRootNode() should be root.");
+is(header2.getRootNode(), root2, "header1.getRootNode() should be root2.");
+is(header4.getRootNode(), root3, "header1.getRootNode() should be root3.");
+//shadow dom with compose
+is(root.getRootNode({ composed: true }), document, "root.getRootNode() with composed flag should be document.");
+is(root2.getRootNode({ composed: true }), document, "root2.getRootNode() with composed flag should be document.");
+is(root3.getRootNode({ composed: true }), frag, "root3.getRootNode() with composed flag should be frag.");
+is(header1.getRootNode({ composed: true }) , document, "header1.getRootNode() with composed flag should be document.");
+is(header2.getRootNode({ composed: true }) , document, "header2.getRootNode() with composed flag should be document.");
+is(header4.getRootNode({ composed: true }) , frag, "head4.getRootNode() with composed flag should be frag.");
+//dom without compose
+is(host.getRootNode(), document, "host.getRootNode() should be document.");
+is(header1.getRootNode(), root, "header1.getRootNode() should be root.");
+is(paragraph1.getRootNode(), root, "paragraph1.getRootNode() should be root.");
+is(frag.getRootNode(), frag, "frag.getRootNode() should be frag.");
+//dom with compose
+is(host.getRootNode({ composed: true }) , document, "host.getRootNode() with composed flag should be document.");
+is(header1.getRootNode({ composed: true }) , document, "header1.getRootNode() with composed flag should be document.");
+is(paragraph1.getRootNode({ composed: true }) , document, "paragraph1.getRootNode() with composed flag should be document.");
+is(frag.getRootNode({ composed: true }) , frag, "frag.getRootNode() with composed flag should be frag.");
+
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/webidl/Node.webidl b/dom/webidl/Node.webidl index 7d18899b0..0a14e3624 100644 --- a/dom/webidl/Node.webidl +++ b/dom/webidl/Node.webidl @@ -38,8 +38,8 @@ interface Node : EventTarget { readonly attribute boolean isConnected; [Pure] readonly attribute Document? ownerDocument; - [Pure, Pref="dom.node.rootNode.enabled"] - readonly attribute Node rootNode; + [Pure] + Node getRootNode(optional GetRootNodeOptions options); [Pure] readonly attribute Node? parentNode; [Pure] @@ -113,3 +113,8 @@ interface Node : EventTarget { readonly attribute AccessibleNode? accessibleNode; #endif }; + +dictionary GetRootNodeOptions { + boolean composed = false; +}; + |