diff options
-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 | ||||
-rw-r--r-- | modules/libpref/init/all.js | 7 | ||||
-rw-r--r-- | testing/web-platform/meta/dom/historical.html.ini | 4 | ||||
-rw-r--r-- | testing/web-platform/meta/dom/interfaces.html.ini | 57 | ||||
-rw-r--r-- | testing/web-platform/meta/dom/nodes/rootNode.html.ini | 15 |
9 files changed, 128 insertions, 89 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; +}; + diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index f3cf4c74e..5ee49372f 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -5383,13 +5383,6 @@ pref("layout.css.color-adjust.enabled", true); pref("dom.audiochannel.audioCompeting", false); pref("dom.audiochannel.audioCompeting.allAgents", false); -// Disable Node.rootNode in release builds. -#ifdef RELEASE_OR_BETA -pref("dom.node.rootNode.enabled", false); -#else -pref("dom.node.rootNode.enabled", true); -#endif - // Default media volume pref("media.default_volume", "1.0"); diff --git a/testing/web-platform/meta/dom/historical.html.ini b/testing/web-platform/meta/dom/historical.html.ini index 6894d4868..42c737606 100644 --- a/testing/web-platform/meta/dom/historical.html.ini +++ b/testing/web-platform/meta/dom/historical.html.ini @@ -12,7 +12,3 @@ expected: FAIL bug: 660660 - [Node member must be nuked: rootNode] - disabled: https://bugzilla.mozilla.org/show_bug.cgi?id=1303802 - bug: 1269155 - diff --git a/testing/web-platform/meta/dom/interfaces.html.ini b/testing/web-platform/meta/dom/interfaces.html.ini index 2a0c6da04..71833f090 100644 --- a/testing/web-platform/meta/dom/interfaces.html.ini +++ b/testing/web-platform/meta/dom/interfaces.html.ini @@ -1,6 +1,5 @@ [interfaces.html] type: testharness - prefs: [dom.node.rootNode.enabled:true] [Document interface: attribute origin] expected: FAIL @@ -48,60 +47,4 @@ [Text interface: document.createTextNode("abc") must inherit property "assignedSlot" with the proper type (2)] expected: FAIL - [Node interface: operation getRootNode(GetRootNodeOptions)] - expected: FAIL - - [Node interface: new Document() must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on new Document() with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: xmlDoc must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.doctype must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.doctype with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.createDocumentFragment() must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.createDocumentFragment() with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: element must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on element with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.querySelector("[id\]").attributes[0\] must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.querySelector("[id\]").attributes[0\] with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.createTextNode("abc") must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.createTextNode("abc") with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError] - expected: FAIL - - [Node interface: document.createComment("abc") must inherit property "getRootNode" with the proper type (17)] - expected: FAIL - - [Node interface: calling getRootNode(GetRootNodeOptions) on document.createComment("abc") with too few arguments must throw TypeError] - expected: FAIL diff --git a/testing/web-platform/meta/dom/nodes/rootNode.html.ini b/testing/web-platform/meta/dom/nodes/rootNode.html.ini deleted file mode 100644 index 59533aebb..000000000 --- a/testing/web-platform/meta/dom/nodes/rootNode.html.ini +++ /dev/null @@ -1,15 +0,0 @@ -[rootNode.html] - type: testharness - prefs: [dom.node.rootNode.enabled:true] - [getRootNode() must return the context object when it does not have any parent] - expected: FAIL - - [getRootNode() must return the parent node of the context object when the context object has a single ancestor not in a document] - expected: FAIL - - [getRootNode() must return the document when a node is in document] - expected: FAIL - - [getRootNode() must return a document fragment when a node is in the fragment] - expected: FAIL - |