[ShadowDOM] Add support for Node.getRootNode(options)
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Sep 2016 01:54:05 +0000 (01:54 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 23 Sep 2016 01:54:05 +0000 (01:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=162457

Reviewed by Ryosuke Niwa.

LayoutTests/imported/w3c:

Rebaseline existing W3C DOM tests now that more checks are passing.

* web-platform-tests/dom/interfaces-expected.txt:
* web-platform-tests/dom/nodes/rootNode-expected.txt:

Source/WebCore:

Add support for Node.getRootNode(options):
- https://dom.spec.whatwg.org/#dom-node-getrootnode

No new tests, rebaselined existing tests.

* dom/EventPath.cpp:
(WebCore::RelatedNodeRetargeter::RelatedNodeRetargeter):
(WebCore::RelatedNodeRetargeter::checkConsistency):
* dom/Node.cpp:
(WebCore::Node::rootNode):
(WebCore::Node::shadowIncludingRoot):
(WebCore::Node::getRootNode):
* dom/Node.h:
* dom/Node.idl:
* editing/Editor.cpp:
(WebCore::correctSpellcheckingPreservingTextCheckingParagraph):
* xml/XPathPath.cpp:
(WebCore::XPath::LocationPath::evaluate):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@206285 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/dom/interfaces-expected.txt
LayoutTests/imported/w3c/web-platform-tests/dom/nodes/rootNode-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/dom/EventPath.cpp
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/Node.idl
Source/WebCore/editing/Editor.cpp
Source/WebCore/xml/XPathPath.cpp

index 1e83c04..68810fd 100644 (file)
@@ -1,5 +1,17 @@
 2016-09-22  Chris Dumez  <cdumez@apple.com>
 
+        [ShadowDOM] Add support for Node.getRootNode(options)
+        https://bugs.webkit.org/show_bug.cgi?id=162457
+
+        Reviewed by Ryosuke Niwa.
+
+        Rebaseline existing W3C DOM tests now that more checks are passing.
+
+        * web-platform-tests/dom/interfaces-expected.txt:
+        * web-platform-tests/dom/nodes/rootNode-expected.txt:
+
+2016-09-22  Chris Dumez  <cdumez@apple.com>
+
         Fix serialization of HTML void elements when they have children
         https://bugs.webkit.org/show_bug.cgi?id=162418
 
index f5a4121..546d3fc 100644 (file)
@@ -192,7 +192,7 @@ PASS Node interface: attribute nodeName
 PASS Node interface: attribute baseURI 
 PASS Node interface: attribute isConnected 
 PASS Node interface: attribute ownerDocument 
-FAIL Node interface: operation getRootNode(GetRootNodeOptions) assert_own_property: interface prototype object missing non-static operation expected property "getRootNode" missing
+PASS Node interface: operation getRootNode(GetRootNodeOptions) 
 PASS Node interface: attribute parentNode 
 PASS Node interface: attribute parentElement 
 PASS Node interface: operation hasChildNodes() 
@@ -349,8 +349,8 @@ PASS Node interface: new Document() must inherit property "nodeName" with the pr
 PASS Node interface: new Document() must inherit property "baseURI" with the proper type (14) 
 PASS Node interface: new Document() must inherit property "isConnected" with the proper type (15) 
 PASS Node interface: new Document() must inherit property "ownerDocument" with the proper type (16) 
-FAIL Node interface: new Document() must inherit property "getRootNode" with the proper type (17) assert_inherits: property "getRootNode" not found in prototype chain
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on new Document() with too few arguments must throw TypeError assert_inherits: property "getRootNode" not found in prototype chain
+PASS Node interface: new Document() must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on new Document() with too few arguments must throw TypeError 
 PASS Node interface: new Document() must inherit property "parentNode" with the proper type (18) 
 PASS Node interface: new Document() must inherit property "parentElement" with the proper type (19) 
 PASS Node interface: new Document() must inherit property "hasChildNodes" with the proper type (20) 
@@ -481,8 +481,8 @@ PASS Node interface: xmlDoc must inherit property "nodeName" with the proper typ
 PASS Node interface: xmlDoc must inherit property "baseURI" with the proper type (14) 
 PASS Node interface: xmlDoc must inherit property "isConnected" with the proper type (15) 
 PASS Node interface: xmlDoc must inherit property "ownerDocument" with the proper type (16) 
-FAIL Node interface: xmlDoc must inherit property "getRootNode" with the proper type (17) assert_inherits: property "getRootNode" not found in prototype chain
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc with too few arguments must throw TypeError assert_inherits: property "getRootNode" not found in prototype chain
+PASS Node interface: xmlDoc must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc with too few arguments must throw TypeError 
 PASS Node interface: xmlDoc must inherit property "parentNode" with the proper type (18) 
 PASS Node interface: xmlDoc must inherit property "parentElement" with the proper type (19) 
 PASS Node interface: xmlDoc must inherit property "hasChildNodes" with the proper type (20) 
@@ -589,8 +589,8 @@ PASS Node interface: document.doctype must inherit property "nodeName" with the
 PASS Node interface: document.doctype must inherit property "baseURI" with the proper type (14) 
 PASS Node interface: document.doctype must inherit property "isConnected" with the proper type (15) 
 PASS Node interface: document.doctype must inherit property "ownerDocument" with the proper type (16) 
-FAIL Node interface: document.doctype must inherit property "getRootNode" with the proper type (17) assert_inherits: property "getRootNode" not found in prototype chain
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on document.doctype with too few arguments must throw TypeError assert_inherits: property "getRootNode" not found in prototype chain
+PASS Node interface: document.doctype must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.doctype with too few arguments must throw TypeError 
 PASS Node interface: document.doctype must inherit property "parentNode" with the proper type (18) 
 PASS Node interface: document.doctype must inherit property "parentElement" with the proper type (19) 
 PASS Node interface: document.doctype must inherit property "hasChildNodes" with the proper type (20) 
@@ -685,8 +685,8 @@ PASS Node interface: document.createDocumentFragment() must inherit property "no
 PASS Node interface: document.createDocumentFragment() must inherit property "baseURI" with the proper type (14) 
 PASS Node interface: document.createDocumentFragment() must inherit property "isConnected" with the proper type (15) 
 PASS Node interface: document.createDocumentFragment() must inherit property "ownerDocument" with the proper type (16) 
-FAIL Node interface: document.createDocumentFragment() must inherit property "getRootNode" with the proper type (17) assert_inherits: property "getRootNode" not found in prototype chain
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on document.createDocumentFragment() with too few arguments must throw TypeError assert_inherits: property "getRootNode" not found in prototype chain
+PASS Node interface: document.createDocumentFragment() must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.createDocumentFragment() with too few arguments must throw TypeError 
 PASS Node interface: document.createDocumentFragment() must inherit property "parentNode" with the proper type (18) 
 PASS Node interface: document.createDocumentFragment() must inherit property "parentElement" with the proper type (19) 
 PASS Node interface: document.createDocumentFragment() must inherit property "hasChildNodes" with the proper type (20) 
@@ -892,8 +892,8 @@ PASS Node interface: element must inherit property "nodeName" with the proper ty
 PASS Node interface: element must inherit property "baseURI" with the proper type (14) 
 PASS Node interface: element must inherit property "isConnected" with the proper type (15) 
 PASS Node interface: element must inherit property "ownerDocument" with the proper type (16) 
-FAIL Node interface: element must inherit property "getRootNode" with the proper type (17) assert_inherits: property "getRootNode" not found in prototype chain
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on element with too few arguments must throw TypeError assert_inherits: property "getRootNode" not found in prototype chain
+PASS Node interface: element must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on element with too few arguments must throw TypeError 
 PASS Node interface: element must inherit property "parentNode" with the proper type (18) 
 PASS Node interface: element must inherit property "parentElement" with the proper type (19) 
 PASS Node interface: element must inherit property "hasChildNodes" with the proper type (20) 
@@ -992,8 +992,8 @@ PASS Node interface: document.querySelector("[id]").attributes[0] must inherit p
 PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "baseURI" with the proper type (14) 
 PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "isConnected" with the proper type (15) 
 PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "ownerDocument" with the proper type (16) 
-FAIL Node interface: document.querySelector("[id]").attributes[0] must inherit property "getRootNode" with the proper type (17) assert_inherits: property "getRootNode" not found in prototype chain
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError assert_inherits: property "getRootNode" not found in prototype chain
+PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.querySelector("[id]").attributes[0] with too few arguments must throw TypeError 
 PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "parentNode" with the proper type (18) 
 PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "parentElement" with the proper type (19) 
 PASS Node interface: document.querySelector("[id]").attributes[0] must inherit property "hasChildNodes" with the proper type (20) 
@@ -1111,8 +1111,8 @@ PASS Node interface: document.createTextNode("abc") must inherit property "nodeN
 PASS Node interface: document.createTextNode("abc") must inherit property "baseURI" with the proper type (14) 
 PASS Node interface: document.createTextNode("abc") must inherit property "isConnected" with the proper type (15) 
 PASS Node interface: document.createTextNode("abc") must inherit property "ownerDocument" with the proper type (16) 
-FAIL Node interface: document.createTextNode("abc") must inherit property "getRootNode" with the proper type (17) assert_inherits: property "getRootNode" not found in prototype chain
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on document.createTextNode("abc") with too few arguments must throw TypeError assert_inherits: property "getRootNode" not found in prototype chain
+PASS Node interface: document.createTextNode("abc") must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.createTextNode("abc") with too few arguments must throw TypeError 
 PASS Node interface: document.createTextNode("abc") must inherit property "parentNode" with the proper type (18) 
 PASS Node interface: document.createTextNode("abc") must inherit property "parentElement" with the proper type (19) 
 PASS Node interface: document.createTextNode("abc") must inherit property "hasChildNodes" with the proper type (20) 
@@ -1212,8 +1212,8 @@ PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inher
 PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "baseURI" with the proper type (14) 
 PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "isConnected" with the proper type (15) 
 PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "ownerDocument" with the proper type (16) 
-FAIL Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "getRootNode" with the proper type (17) assert_inherits: property "getRootNode" not found in prototype chain
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError assert_inherits: property "getRootNode" not found in prototype chain
+PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on xmlDoc.createProcessingInstruction("abc", "def") with too few arguments must throw TypeError 
 PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentNode" with the proper type (18) 
 PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "parentElement" with the proper type (19) 
 PASS Node interface: xmlDoc.createProcessingInstruction("abc", "def") must inherit property "hasChildNodes" with the proper type (20) 
@@ -1306,8 +1306,8 @@ PASS Node interface: document.createComment("abc") must inherit property "nodeNa
 PASS Node interface: document.createComment("abc") must inherit property "baseURI" with the proper type (14) 
 PASS Node interface: document.createComment("abc") must inherit property "isConnected" with the proper type (15) 
 PASS Node interface: document.createComment("abc") must inherit property "ownerDocument" with the proper type (16) 
-FAIL Node interface: document.createComment("abc") must inherit property "getRootNode" with the proper type (17) assert_inherits: property "getRootNode" not found in prototype chain
-FAIL Node interface: calling getRootNode(GetRootNodeOptions) on document.createComment("abc") with too few arguments must throw TypeError assert_inherits: property "getRootNode" not found in prototype chain
+PASS Node interface: document.createComment("abc") must inherit property "getRootNode" with the proper type (17) 
+PASS Node interface: calling getRootNode(GetRootNodeOptions) on document.createComment("abc") with too few arguments must throw TypeError 
 PASS Node interface: document.createComment("abc") must inherit property "parentNode" with the proper type (18) 
 PASS Node interface: document.createComment("abc") must inherit property "parentElement" with the proper type (19) 
 PASS Node interface: document.createComment("abc") must inherit property "hasChildNodes" with the proper type (20) 
index bad9e62..aa8710e 100644 (file)
@@ -1,6 +1,6 @@
 
-FAIL getRootNode() must return the context object when it does not have any parent element.getRootNode is not a function. (In 'element.getRootNode()', 'element.getRootNode' is undefined)
-FAIL getRootNode() must return the parent node of the context object when the context object has a single ancestor not in a document element.getRootNode is not a function. (In 'element.getRootNode()', 'element.getRootNode' is undefined)
-FAIL getRootNode() must return the document when a node is in document element.getRootNode is not a function. (In 'element.getRootNode()', 'element.getRootNode' is undefined)
-FAIL getRootNode() must return a document fragment when a node is in the fragment element.getRootNode is not a function. (In 'element.getRootNode()', 'element.getRootNode' is undefined)
+PASS getRootNode() must return the context object when it does not have any parent 
+PASS getRootNode() must return the parent node of the context object when the context object has a single ancestor not in a document 
+PASS getRootNode() must return the document when a node is in document 
+PASS getRootNode() must return a document fragment when a node is in the fragment 
 
index 090dbbc..328c9b0 100644 (file)
@@ -1,3 +1,29 @@
+2016-09-22  Chris Dumez  <cdumez@apple.com>
+
+        [ShadowDOM] Add support for Node.getRootNode(options)
+        https://bugs.webkit.org/show_bug.cgi?id=162457
+
+        Reviewed by Ryosuke Niwa.
+
+        Add support for Node.getRootNode(options):
+        - https://dom.spec.whatwg.org/#dom-node-getrootnode
+
+        No new tests, rebaselined existing tests.
+
+        * dom/EventPath.cpp:
+        (WebCore::RelatedNodeRetargeter::RelatedNodeRetargeter):
+        (WebCore::RelatedNodeRetargeter::checkConsistency):
+        * dom/Node.cpp:
+        (WebCore::Node::rootNode):
+        (WebCore::Node::shadowIncludingRoot):
+        (WebCore::Node::getRootNode):
+        * dom/Node.h:
+        * dom/Node.idl:
+        * editing/Editor.cpp:
+        (WebCore::correctSpellcheckingPreservingTextCheckingParagraph):
+        * xml/XPathPath.cpp:
+        (WebCore::XPath::LocationPath::evaluate):
+
 2016-09-22  Brady Eidson  <beidson@apple.com>
 
         IDBIndex.openCursor() matches indices on multiple object stores.
index 5b5bb96..887b3d3 100644 (file)
@@ -290,7 +290,7 @@ RelatedNodeRetargeter::RelatedNodeRetargeter(Node& relatedNode, Node& target)
     if (lowestCommonAncestorIsDocumentScope && !relatedNode.inDocument() && !target.inDocument()) {
         Node& targetAncestorInDocumentScope = i ? *downcast<ShadowRoot>(m_ancestorTreeScopes[i - 1]->rootNode()).shadowHost() : target;
         Node& relatedNodeAncestorInDocumentScope = j ? *downcast<ShadowRoot>(targetTreeScopeAncestors[j - 1]->rootNode()).shadowHost() : relatedNode;
-        if (targetAncestorInDocumentScope.rootNode() != relatedNodeAncestorInDocumentScope.rootNode()) {
+        if (&targetAncestorInDocumentScope.rootNode() != &relatedNodeAncestorInDocumentScope.rootNode()) {
             m_hasDifferentTreeRoot = true;
             m_retargetedRelatedNode = moveOutOfAllShadowRoots(relatedNode);
             return;
@@ -365,7 +365,7 @@ void RelatedNodeRetargeter::checkConsistency(Node& currentTarget)
     // http://w3c.github.io/webcomponents/spec/shadow/#dfn-retargeting-algorithm
     Node& base = currentTarget;
     for (Node* targetAncestor = &m_relatedNode; targetAncestor; targetAncestor = targetAncestor->parentOrShadowHostNode()) {
-        if (targetAncestor->rootNode()->containsIncludingShadowDOM(&base)) {
+        if (targetAncestor->rootNode().containsIncludingShadowDOM(&base)) {
             ASSERT(m_retargetedRelatedNode == targetAncestor);
             return;
         }
index 98d94e6..a0d1cab 100644 (file)
@@ -1163,16 +1163,31 @@ Element* Node::parentOrShadowHostElement() const
     return downcast<Element>(parent);
 }
 
-Node* Node::rootNode() const
+Node& Node::rootNode() const
 {
     if (isInTreeScope())
-        return &treeScope().rootNode();
+        return treeScope().rootNode();
 
     Node* node = const_cast<Node*>(this);
     Node* highest = node;
     for (; node; node = node->parentNode())
         highest = node;
-    return highest;
+    return *highest;
+}
+
+// https://dom.spec.whatwg.org/#concept-shadow-including-root
+Node& Node::shadowIncludingRoot() const
+{
+    auto& root = rootNode();
+    if (!is<ShadowRoot>(root))
+        return root;
+    auto* host = downcast<ShadowRoot>(root).host();
+    return host ? host->shadowIncludingRoot() : root;
+}
+
+Node& Node::getRootNode(const GetRootNodeOptions& options) const
+{
+    return options.composed ? shadowIncludingRoot() : rootNode();
 }
 
 Node::InsertionNotificationRequest Node::insertedInto(ContainerNode& insertionPoint)
index c9dc94d..e26c332 100644 (file)
@@ -273,7 +273,13 @@ public:
     ContainerNode* parentInComposedTree() const;
     Element* parentOrShadowHostElement() const;
     void setParentNode(ContainerNode*);
-    Node* rootNode() const;
+    Node& rootNode() const;
+    Node& shadowIncludingRoot() const;
+
+    struct GetRootNodeOptions {
+        bool composed;
+    };
+    Node& getRootNode(const GetRootNodeOptions&) const;
 
     // Use when it's guaranteed to that shadowHost is null.
     ContainerNode* parentNodeGuaranteedHostFree() const;
index fee215c..11d1e6f 100644 (file)
 
     boolean contains(Node? other);
 
+    [EnabledAtRuntime=ShadowDOM] Node getRootNode(optional GetRootNodeOptions options);
     [EnabledAtRuntime=ShadowDOM, ImplementedAs=inDocument] readonly attribute boolean isConnected;
 
     readonly attribute Element parentElement;
 };
+
+dictionary GetRootNodeOptions {
+  boolean composed = false;
+};
index c5cde04..69dd663 100644 (file)
@@ -2470,18 +2470,18 @@ static bool isAutomaticTextReplacementType(TextCheckingType type)
 
 static void correctSpellcheckingPreservingTextCheckingParagraph(TextCheckingParagraph& paragraph, PassRefPtr<Range> rangeToReplace, const String& replacement, int resultLocation, int resultLength)
 {
-    ContainerNode* scope = downcast<ContainerNode>(paragraph.paragraphRange()->startContainer().rootNode());
+    auto& scope = downcast<ContainerNode>(paragraph.paragraphRange()->startContainer().rootNode());
 
     size_t paragraphLocation;
     size_t paragraphLength;
-    TextIterator::getLocationAndLengthFromRange(scope, paragraph.paragraphRange().get(), paragraphLocation, paragraphLength);
+    TextIterator::getLocationAndLengthFromRange(&scope, paragraph.paragraphRange().get(), paragraphLocation, paragraphLength);
 
     applyCommand(SpellingCorrectionCommand::create(rangeToReplace, replacement));
 
     // TextCheckingParagraph may be orphaned after SpellingCorrectionCommand mutated DOM.
     // See <rdar://10305315>, http://webkit.org/b/89526.
 
-    RefPtr<Range> newParagraphRange = TextIterator::rangeFromLocationAndLength(scope, paragraphLocation, paragraphLength + replacement.length() - resultLength);
+    RefPtr<Range> newParagraphRange = TextIterator::rangeFromLocationAndLength(&scope, paragraphLocation, paragraphLength + replacement.length() - resultLength);
 
     paragraph = TextCheckingParagraph(TextIterator::subrange(newParagraphRange.get(), resultLocation, replacement.length()), newParagraphRange);
 }
index d44ec62..a20524d 100644 (file)
@@ -89,7 +89,7 @@ Value LocationPath::evaluate() const
     // logical treatment of where you would expect the "root" to be.
     Node* context = evaluationContext.node.get();
     if (m_isAbsolute && !context->isDocumentNode())
-        context = context->rootNode();
+        context = &context->rootNode();
 
     NodeSet nodes;
     nodes.append(context);