Title: [121079] trunk
Revision
121079
Author
hay...@chromium.org
Date
2012-06-22 17:31:02 -0700 (Fri, 22 Jun 2012)

Log Message

[Shadow] ShadowRoot.activeElement should use the result of re-targeting algorithm.
https://bugs.webkit.org/show_bug.cgi?id=89763

Reviewed by Dimitri Glazkov.

Source/WebCore:

Use the result of the re-targeting algorithm in calculating
shadow root's activeElement so that ShadowRoot.activeElement returns
a focused distributed node correctly as the algorithm says.

The spec is:
https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#active-element

Tests: fast/dom/shadow/shadow-root-activeElement.html

* dom/EventDispatcher.cpp:
(WebCore):
(WebCore::EventRelatedTargetAdjuster::adjust):
(WebCore::EventDispatcher::ensureEventAncestors):
* dom/TreeScope.cpp:
(WebCore::TreeScope::focusedNode):
* html/shadow/InsertionPoint.h:
(WebCore::InsertionPoint::contains):

LayoutTests:

* fast/dom/shadow/shadow-root-activeElement-expected.txt:
* fast/dom/shadow/shadow-root-activeElement.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (121078 => 121079)


--- trunk/LayoutTests/ChangeLog	2012-06-23 00:23:58 UTC (rev 121078)
+++ trunk/LayoutTests/ChangeLog	2012-06-23 00:31:02 UTC (rev 121079)
@@ -1,3 +1,13 @@
+2012-06-22  Hayato Ito  <hay...@chromium.org>
+
+        [Shadow] ShadowRoot.activeElement should use the result of re-targeting algorithm.
+        https://bugs.webkit.org/show_bug.cgi?id=89763
+
+        Reviewed by Dimitri Glazkov.
+
+        * fast/dom/shadow/shadow-root-activeElement-expected.txt:
+        * fast/dom/shadow/shadow-root-activeElement.html:
+
 2012-06-22  Kenneth Russell  <k...@google.com>
 
         Unreviewed Chromium gardening. Suppressed additional test failures

Modified: trunk/LayoutTests/fast/dom/shadow/shadow-root-activeElement-expected.txt (121078 => 121079)


--- trunk/LayoutTests/fast/dom/shadow/shadow-root-activeElement-expected.txt	2012-06-23 00:23:58 UTC (rev 121078)
+++ trunk/LayoutTests/fast/dom/shadow/shadow-root-activeElement-expected.txt	2012-06-23 00:31:02 UTC (rev 121079)
@@ -3,22 +3,24 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-
-PASS shadowRoot.activeElement is defined.
-PASS shadowRootInside.activeElement is defined.
-PASS childInBody.focus();document.activeElement is childInBody
-PASS childInBody.focus();shadowRoot.activeElement is null
-PASS childInBody.focus();shadowRootInside.activeElement is null
-PASS childInTreeOne.focus();document.activeElement is shadowHost
-PASS childInTreeOne.focus();shadowRoot.activeElement is childInTreeOne
-PASS childInTreeOne.focus();shadowRootInside.activeElement is null
-PASS childInTreeTwo.focus();document.activeElement is shadowHost
-PASS childInTreeTwo.focus();shadowRoot.activeElement is shadowHostInside
-PASS childInTreeTwo.focus();shadowRootInside.activeElement is childInTreeTwo
-childInTreeTwo.blur();
+PASS shadowRoot1.activeElement is defined.
+PASS shadowRoot2.activeElement is defined.
+PASS nodeInDocument.focus(); document.activeElement is nodeInDocument
+PASS nodeInDocument.focus(); shadowRoot1.activeElement is null
+PASS nodeInDocument.focus(); shadowRoot2.activeElement is null
+PASS distributedLightChild.focus(); document.activeElement is distributedLightChild
+PASS distributedLightChild.focus(); shadowRoot1.activeElement is distributedLightChild
+PASS distributedLightChild.focus(); shadowRoot2.activeElement is null
+PASS childInShadowRoot1.focus(); document.activeElement is shadowHost1
+PASS childInShadowRoot1.focus(); shadowRoot1.activeElement is childInShadowRoot1
+PASS childInShadowRoot1.focus(); shadowRoot2.activeElement is null
+PASS childInShadowRoot2.focus(); document.activeElement is shadowHost1
+PASS childInShadowRoot2.focus(); shadowRoot1.activeElement is shadowHost2
+PASS childInShadowRoot2.focus(); shadowRoot2.activeElement is childInShadowRoot2
+childInShadowRoot2.blur();
 PASS document.activeElement is document.body
-PASS shadowRoot.activeElement is null
-PASS shadowRootInside.activeElement is null
+PASS shadowRoot1.activeElement is null
+PASS shadowRoot2.activeElement is null
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/dom/shadow/shadow-root-activeElement.html (121078 => 121079)


--- trunk/LayoutTests/fast/dom/shadow/shadow-root-activeElement.html	2012-06-23 00:23:58 UTC (rev 121078)
+++ trunk/LayoutTests/fast/dom/shadow/shadow-root-activeElement.html	2012-06-23 00:31:02 UTC (rev 121079)
@@ -2,9 +2,11 @@
 <html>
 <head>
 <script src=""
+<script src=""
 </head>
 <body>
-<div id="console">
+<div id="console"></div>
+<div id="sandbox">
 </div>
 <script>
 description("This tests the activeElement property of a ShadowRoot.");
@@ -15,51 +17,51 @@
 if (window.testRunner)
     testRunner.dumpAsText();
 
-var childInBody = document.createElement("p");
-childInBody.tabIndex = "1";
-document.body.appendChild(childInBody);
+document.getElementById('sandbox').appendChild(
+    createDOM('div', {},
+              createDOM('div', {'id': 'node-in-document', 'tabindex': 1}),
+              createDOM('div', {'id': 'shadow-host-1'},
+                        createShadowRoot(
+                            createDOM('div', {'id': 'shadow-host-2'},
+                                      createShadowRoot(
+                                          createDOM('div', {'id': 'child-in-shadow-root-2', 'tabindex': 1}))),
+                            createDOM('div', {'id': 'child-in-shadow-root-1', 'tabindex': 1}),
+                            createDOM('content', {'select': '#distributed-light-child'})),
+                        createDOM('div', {'id': 'distributed-light-child', 'tabindex': 1}))));
 
-// First ShodowHost
-var shadowHost = document.createElement("div");
-document.body.appendChild(shadowHost);
-var shadowRoot = new WebKitShadowRoot(shadowHost);
+var shadowHost1 = getNodeInShadowTreeStack('shadow-host-1');
+var shadowHost2 = getNodeInShadowTreeStack('shadow-host-1/shadow-host-2');
+var shadowRoot1 = getNodeInShadowTreeStack('shadow-host-1/');
+var shadowRoot2 = getNodeInShadowTreeStack('shadow-host-1/shadow-host-2/');
 
-// Second ShadowHost
-shadowHostInside = document.createElement("div");
-shadowRoot.appendChild(shadowHostInside);
-var shadowRootInside = new WebKitShadowRoot(shadowHostInside);
+var nodeInDocument = document.getElementById('node-in-document');
+var distributedLightChild = document.getElementById('distributed-light-child');
+var childInShadowRoot1 = getNodeInShadowTreeStack('shadow-host-1/child-in-shadow-root-1');
+var childInShadowRoot2 = getNodeInShadowTreeStack('shadow-host-1/shadow-host-2/child-in-shadow-root-2');
 
-// Add a child inside first Shadow host
-var childInTreeOne = document.createElement("p");
-childInTreeOne.setAttribute("id", "childInTreeOne");
-childInTreeOne.tabIndex = "1";
-shadowRoot.appendChild(childInTreeOne);
+shouldBeDefined("shadowRoot1.activeElement");
+shouldBeDefined("shadowRoot2.activeElement");
 
-// Add a child inside second shadow host
-var childInTreeTwo = document.createElement("p");
-childInTreeTwo.setAttribute("id", "childInTreeTwo");
-childInTreeTwo.tabIndex = "1";
-shadowRootInside.appendChild(childInTreeTwo);
+shouldBe("nodeInDocument.focus(); document.activeElement", "nodeInDocument");
+shouldBe("nodeInDocument.focus(); shadowRoot1.activeElement", "null");
+shouldBe("nodeInDocument.focus(); shadowRoot2.activeElement", "null");
 
-shouldBeDefined("shadowRoot.activeElement");
-shouldBeDefined("shadowRootInside.activeElement");
+shouldBe("distributedLightChild.focus(); document.activeElement", "distributedLightChild");
+shouldBe("distributedLightChild.focus(); shadowRoot1.activeElement", "distributedLightChild");
+shouldBe("distributedLightChild.focus(); shadowRoot2.activeElement", "null");
 
-shouldBe("childInBody.focus();document.activeElement", "childInBody");
-shouldBe("childInBody.focus();shadowRoot.activeElement", "null");
-shouldBe("childInBody.focus();shadowRootInside.activeElement", "null");
+shouldBe("childInShadowRoot1.focus(); document.activeElement", "shadowHost1");
+shouldBe("childInShadowRoot1.focus(); shadowRoot1.activeElement", "childInShadowRoot1");
+shouldBe("childInShadowRoot1.focus(); shadowRoot2.activeElement", "null");
 
-shouldBe("childInTreeOne.focus();document.activeElement", "shadowHost");
-shouldBe("childInTreeOne.focus();shadowRoot.activeElement", "childInTreeOne");
-shouldBe("childInTreeOne.focus();shadowRootInside.activeElement", "null");
+shouldBe("childInShadowRoot2.focus(); document.activeElement", "shadowHost1");
+shouldBe("childInShadowRoot2.focus(); shadowRoot1.activeElement", "shadowHost2");
+shouldBe("childInShadowRoot2.focus(); shadowRoot2.activeElement", "childInShadowRoot2");
 
-shouldBe("childInTreeTwo.focus();document.activeElement", "shadowHost");
-shouldBe("childInTreeTwo.focus();shadowRoot.activeElement", "shadowHostInside");
-shouldBe("childInTreeTwo.focus();shadowRootInside.activeElement", "childInTreeTwo");
-
-evalAndLog("childInTreeTwo.blur();");
+evalAndLog("childInShadowRoot2.blur();");
 shouldBe("document.activeElement", "document.body");
-shouldBe("shadowRoot.activeElement", "null");
-shouldBe("shadowRootInside.activeElement", "null");
+shouldBe("shadowRoot1.activeElement", "null");
+shouldBe("shadowRoot2.activeElement", "null");
 
 var successfullyParsed = true;
 </script>

Modified: trunk/Source/WebCore/ChangeLog (121078 => 121079)


--- trunk/Source/WebCore/ChangeLog	2012-06-23 00:23:58 UTC (rev 121078)
+++ trunk/Source/WebCore/ChangeLog	2012-06-23 00:31:02 UTC (rev 121079)
@@ -1,3 +1,28 @@
+2012-06-22  Hayato Ito  <hay...@chromium.org>
+
+        [Shadow] ShadowRoot.activeElement should use the result of re-targeting algorithm.
+        https://bugs.webkit.org/show_bug.cgi?id=89763
+
+        Reviewed by Dimitri Glazkov.
+
+        Use the result of the re-targeting algorithm in calculating
+        shadow root's activeElement so that ShadowRoot.activeElement returns
+        a focused distributed node correctly as the algorithm says.
+
+        The spec is:
+        https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html#active-element
+
+        Tests: fast/dom/shadow/shadow-root-activeElement.html
+
+        * dom/EventDispatcher.cpp:
+        (WebCore):
+        (WebCore::EventRelatedTargetAdjuster::adjust):
+        (WebCore::EventDispatcher::ensureEventAncestors):
+        * dom/TreeScope.cpp:
+        (WebCore::TreeScope::focusedNode):
+        * html/shadow/InsertionPoint.h:
+        (WebCore::InsertionPoint::contains):
+
 2012-06-22  James Robinson  <jam...@chromium.org>
 
         [chromium] LayerRendererChromium is not getting visibility messages in single threaded compositing mode.

Modified: trunk/Source/WebCore/dom/EventDispatcher.cpp (121078 => 121079)


--- trunk/Source/WebCore/dom/EventDispatcher.cpp	2012-06-23 00:23:58 UTC (rev 121078)
+++ trunk/Source/WebCore/dom/EventDispatcher.cpp	2012-06-23 00:31:02 UTC (rev 121079)
@@ -51,12 +51,6 @@
 
 static HashSet<Node*>* gNodesDispatchingSimulatedClicks = 0;
 
-static inline bool isAssignedTo(const Node* node, const InsertionPoint* insertionPoint)
-{
-    ASSERT(insertionPoint);
-    return node && (insertionPoint->contains(node) || (node->isShadowRoot() && toShadowRoot(node)->assignedTo() == insertionPoint));
-}
-
 EventRelatedTargetAdjuster::EventRelatedTargetAdjuster(PassRefPtr<Node> node, PassRefPtr<Node> relatedTarget)
     : m_node(node)
     , m_relatedTarget(relatedTarget)
@@ -74,7 +68,7 @@
         Node* node = walker.get();
         if (relatedTargetStack.isEmpty())
             relatedTargetStack.append(node);
-        else if (isInsertionPoint(node) && isAssignedTo(lastNode, toInsertionPoint(node)))
+        else if (isInsertionPoint(node) && toInsertionPoint(node)->contains(lastNode))
             relatedTargetStack.append(relatedTargetStack.last());
         TreeScope* scope = node->treeScope();
         // Skips adding a node to the map if treeScope does not change. Just for the performance optimization.
@@ -226,7 +220,7 @@
         Node* node = walker.get();
         if (targetStack.isEmpty())
             targetStack.append(eventTargetRespectingSVGTargetRules(node));
-        else if (isInsertionPoint(node) && isAssignedTo(last, toInsertionPoint(node)))
+        else if (isInsertionPoint(node) && toInsertionPoint(node)->contains(last))
             targetStack.append(targetStack.last());
         m_ancestors.append(EventContext(node, eventTargetRespectingSVGTargetRules(node), targetStack.last()));
         if (!inDocument)

Modified: trunk/Source/WebCore/dom/TreeScope.cpp (121078 => 121079)


--- trunk/Source/WebCore/dom/TreeScope.cpp	2012-06-23 00:23:58 UTC (rev 121078)
+++ trunk/Source/WebCore/dom/TreeScope.cpp	2012-06-23 00:31:02 UTC (rev 121079)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "TreeScope.h"
 
+#include "ComposedShadowTreeWalker.h"
 #include "ContainerNode.h"
 #include "ContextFeatures.h"
 #include "DOMSelection.h"
@@ -38,6 +39,7 @@
 #include "HTMLFrameOwnerElement.h"
 #include "HTMLMapElement.h"
 #include "HTMLNames.h"
+#include "InsertionPoint.h"
 #include "Page.h"
 #include "ShadowRoot.h"
 #include "TreeScopeAdopter.h"
@@ -224,17 +226,23 @@
         node = focusedFrameOwnerElement(document->page()->focusController()->focusedFrame(), document->frame());
     if (!node)
         return 0;
-
-    TreeScope* treeScope = node->treeScope();
-
-    while (treeScope != this && treeScope != document) {
-        node = toShadowRoot(treeScope->rootNode())->host();
-        treeScope = node->treeScope();
+    Vector<Node*> targetStack;
+    Node* last = 0;
+    for (ComposedShadowTreeParentWalker walker(node); walker.get(); walker.parentIncludingInsertionPointAndShadowRoot()) {
+        Node* node = walker.get();
+        if (targetStack.isEmpty())
+            targetStack.append(node);
+        else if (isInsertionPoint(node) && toInsertionPoint(node)->contains(last))
+            targetStack.append(targetStack.last());
+        if (node == rootNode())
+            return targetStack.last();
+        last = node;
+        if (node->isShadowRoot()) {
+            ASSERT(!targetStack.isEmpty());
+            targetStack.removeLast();
+        }
     }
-    if (this != treeScope)
-        return 0;
-
-    return node;
+    return 0;
 }
 
 static void listTreeScopes(Node* node, Vector<TreeScope*, 5>& treeScopes)

Modified: trunk/Source/WebCore/html/shadow/InsertionPoint.h (121078 => 121079)


--- trunk/Source/WebCore/html/shadow/InsertionPoint.h	2012-06-23 00:23:58 UTC (rev 121078)
+++ trunk/Source/WebCore/html/shadow/InsertionPoint.h	2012-06-23 00:31:02 UTC (rev 121079)
@@ -34,6 +34,7 @@
 #include "ContentDistributor.h"
 #include "HTMLElement.h"
 #include "HTMLNames.h"
+#include "ShadowRoot.h"
 #include <wtf/Forward.h>
 
 namespace WebCore {
@@ -57,7 +58,7 @@
     virtual bool isInsertionPoint() const OVERRIDE { return true; }
 
     size_t indexOf(Node* node) const { return m_distribution.find(node); }
-    bool contains(const Node* node) const { return m_distribution.contains(const_cast<Node*>(node)); }
+    bool contains(const Node* node) const { return m_distribution.contains(const_cast<Node*>(node)) || (node->isShadowRoot() && toShadowRoot(node)->assignedTo() == this); }
     size_t size() const { return m_distribution.size(); }
     Node* at(size_t index)  const { return m_distribution.at(index).get(); }
     Node* first() const { return m_distribution.isEmpty() ? 0 : m_distribution.first().get(); }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to