Title: [206285] trunk
Revision
206285
Author
cdu...@apple.com
Date
2016-09-22 18:54:05 -0700 (Thu, 22 Sep 2016)

Log Message

[ShadowDOM] Add support for Node.getRootNode(options)
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):

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (206284 => 206285)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2016-09-23 01:54:05 UTC (rev 206285)
@@ -1,5 +1,17 @@
 2016-09-22  Chris Dumez  <cdu...@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  <cdu...@apple.com>
+
         Fix serialization of HTML void elements when they have children
         https://bugs.webkit.org/show_bug.cgi?id=162418
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/interfaces-expected.txt (206284 => 206285)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/interfaces-expected.txt	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/interfaces-expected.txt	2016-09-23 01:54:05 UTC (rev 206285)
@@ -192,7 +192,7 @@
 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 "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 "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 "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 "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 "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 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 "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 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 "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) 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/rootNode-expected.txt (206284 => 206285)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/rootNode-expected.txt	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/dom/nodes/rootNode-expected.txt	2016-09-23 01:54:05 UTC (rev 206285)
@@ -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 
 

Modified: trunk/Source/WebCore/ChangeLog (206284 => 206285)


--- trunk/Source/WebCore/ChangeLog	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/Source/WebCore/ChangeLog	2016-09-23 01:54:05 UTC (rev 206285)
@@ -1,3 +1,29 @@
+2016-09-22  Chris Dumez  <cdu...@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  <beid...@apple.com>
 
         IDBIndex.openCursor() matches indices on multiple object stores.

Modified: trunk/Source/WebCore/dom/EventPath.cpp (206284 => 206285)


--- trunk/Source/WebCore/dom/EventPath.cpp	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/Source/WebCore/dom/EventPath.cpp	2016-09-23 01:54:05 UTC (rev 206285)
@@ -290,7 +290,7 @@
     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 @@
     // 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;
         }

Modified: trunk/Source/WebCore/dom/Node.cpp (206284 => 206285)


--- trunk/Source/WebCore/dom/Node.cpp	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/Source/WebCore/dom/Node.cpp	2016-09-23 01:54:05 UTC (rev 206285)
@@ -1163,18 +1163,33 @@
     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)
 {
     ASSERT(insertionPoint.inDocument() || isContainerNode());

Modified: trunk/Source/WebCore/dom/Node.h (206284 => 206285)


--- trunk/Source/WebCore/dom/Node.h	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/Source/WebCore/dom/Node.h	2016-09-23 01:54:05 UTC (rev 206285)
@@ -273,8 +273,14 @@
     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;
     // Returns the parent node, but null if the parent node is a ShadowRoot.

Modified: trunk/Source/WebCore/dom/Node.idl (206284 => 206285)


--- trunk/Source/WebCore/dom/Node.idl	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/Source/WebCore/dom/Node.idl	2016-09-23 01:54:05 UTC (rev 206285)
@@ -90,7 +90,12 @@
 
     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;
+};

Modified: trunk/Source/WebCore/editing/Editor.cpp (206284 => 206285)


--- trunk/Source/WebCore/editing/Editor.cpp	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/Source/WebCore/editing/Editor.cpp	2016-09-23 01:54:05 UTC (rev 206285)
@@ -2470,11 +2470,11 @@
 
 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));
 
@@ -2481,7 +2481,7 @@
     // 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);
 }

Modified: trunk/Source/WebCore/xml/XPathPath.cpp (206284 => 206285)


--- trunk/Source/WebCore/xml/XPathPath.cpp	2016-09-23 01:15:53 UTC (rev 206284)
+++ trunk/Source/WebCore/xml/XPathPath.cpp	2016-09-23 01:54:05 UTC (rev 206285)
@@ -89,7 +89,7 @@
     // 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);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to