- Revision
- 118945
- Author
- [email protected]
- Date
- 2012-05-30 11:36:00 -0700 (Wed, 30 May 2012)
Log Message
comparePositions in htmlediting should consider nested Shadow DOM.
https://bugs.webkit.org/show_bug.cgi?id=87623
Reviewed by Ryosuke Niwa.
Source/WebCore:
comparePositions in htmlediting.cpp didn't consider nested Shadow DOM.
This patch makes it possible to compare the nodes in nested Shadow DOM.
The algorithm is: we calculate the common tree scope of node A and B, and
adjust the nodes to the treeScope, then compare them. If the adjusted nodes
are the same, we check the shadow descendent of each node.
Test: editing/shadow/compare-positions-in-nested-shadow.html
* dom/TreeScope.cpp:
(WebCore::listTreeScopes):
(WebCore):
(WebCore::commonTreeScope):
* dom/TreeScope.h:
(WebCore):
* editing/htmlediting.cpp:
(WebCore::comparePositions):
LayoutTests:
* editing/shadow/compare-positions-in-nested-shadow-expected.txt: Added.
* editing/shadow/compare-positions-in-nested-shadow.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (118944 => 118945)
--- trunk/LayoutTests/ChangeLog 2012-05-30 18:33:02 UTC (rev 118944)
+++ trunk/LayoutTests/ChangeLog 2012-05-30 18:36:00 UTC (rev 118945)
@@ -1,3 +1,13 @@
+2012-05-30 Shinya Kawanaka <[email protected]>
+
+ comparePositions in htmlediting should consider nested Shadow DOM.
+ https://bugs.webkit.org/show_bug.cgi?id=87623
+
+ Reviewed by Ryosuke Niwa.
+
+ * editing/shadow/compare-positions-in-nested-shadow-expected.txt: Added.
+ * editing/shadow/compare-positions-in-nested-shadow.html: Added.
+
2012-05-30 Erik Arvidsson <[email protected]>
[V8] Clean up V8LazyEventListener to use one less function call
Added: trunk/LayoutTests/editing/shadow/compare-positions-in-nested-shadow-expected.txt (0 => 118945)
--- trunk/LayoutTests/editing/shadow/compare-positions-in-nested-shadow-expected.txt (rev 0)
+++ trunk/LayoutTests/editing/shadow/compare-positions-in-nested-shadow-expected.txt 2012-05-30 18:36:00 UTC (rev 118945)
@@ -0,0 +1,7 @@
+PASS selection2.anchorNode is selection2.focusNode
+PASS selection2.anchorOffset is 5
+PASS selection2.focusOffset is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/editing/shadow/compare-positions-in-nested-shadow.html (0 => 118945)
--- trunk/LayoutTests/editing/shadow/compare-positions-in-nested-shadow.html (rev 0)
+++ trunk/LayoutTests/editing/shadow/compare-positions-in-nested-shadow.html 2012-05-30 18:36:00 UTC (rev 118945)
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<body>
+<script src=""
+<script src=""
+<script src=""
+
+<div id="host1"></div>
+<div id="host2"></div>
+<pre id="console"></pre>
+
+<script>
+function createBox(name) {
+ var div = document.createElement('div');
+ div.style.width = '100px';
+ div.style.height = '100px';
+ return div;
+}
+
+function createNestedShadowDOM(host, content) {
+ var shadowRoot = new WebKitShadowRoot(host);
+ var div = document.createElement('div');
+ shadowRoot.appendChild(div);
+
+ var nestedShadowRoot = new WebKitShadowRoot(div);
+ var divInNestedShadowRoot = document.createElement('div');
+ divInNestedShadowRoot.innerHTML = content;
+ nestedShadowRoot.appendChild(divInNestedShadowRoot);
+
+ return nestedShadowRoot;
+}
+
+var nestedShadowRoot1 = createNestedShadowDOM(host1, 'FUTAMI');
+var nestedShadowRoot2 = createNestedShadowDOM(host2, 'AMAMI');
+
+var div1 = nestedShadowRoot1.firstChild;
+var div2 = nestedShadowRoot2.firstChild;
+
+if (window.eventSender) {
+ mouseMoveToElem(div2);
+ eventSender.mouseDown();
+ mouseMoveToElem(div1);
+ eventSender.mouseUp();
+
+ var selection2 = nestedShadowRoot2.getSelection();
+ shouldBe('selection2.anchorNode', 'selection2.focusNode');
+
+ shouldBe('selection2.anchorOffset', '5');
+ shouldBe('selection2.focusOffset', '0');
+}
+
+var successfullyParsed = true;
+</script>
+
+<script src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (118944 => 118945)
--- trunk/Source/WebCore/ChangeLog 2012-05-30 18:33:02 UTC (rev 118944)
+++ trunk/Source/WebCore/ChangeLog 2012-05-30 18:36:00 UTC (rev 118945)
@@ -1,3 +1,28 @@
+2012-05-30 Shinya Kawanaka <[email protected]>
+
+ comparePositions in htmlediting should consider nested Shadow DOM.
+ https://bugs.webkit.org/show_bug.cgi?id=87623
+
+ Reviewed by Ryosuke Niwa.
+
+ comparePositions in htmlediting.cpp didn't consider nested Shadow DOM.
+ This patch makes it possible to compare the nodes in nested Shadow DOM.
+
+ The algorithm is: we calculate the common tree scope of node A and B, and
+ adjust the nodes to the treeScope, then compare them. If the adjusted nodes
+ are the same, we check the shadow descendent of each node.
+
+ Test: editing/shadow/compare-positions-in-nested-shadow.html
+
+ * dom/TreeScope.cpp:
+ (WebCore::listTreeScopes):
+ (WebCore):
+ (WebCore::commonTreeScope):
+ * dom/TreeScope.h:
+ (WebCore):
+ * editing/htmlediting.cpp:
+ (WebCore::comparePositions):
+
2012-05-30 Erik Arvidsson <[email protected]>
[V8] Clean up V8LazyEventListener to use one less function call
Modified: trunk/Source/WebCore/dom/TreeScope.cpp (118944 => 118945)
--- trunk/Source/WebCore/dom/TreeScope.cpp 2012-05-30 18:33:02 UTC (rev 118944)
+++ trunk/Source/WebCore/dom/TreeScope.cpp 2012-05-30 18:36:00 UTC (rev 118945)
@@ -41,6 +41,7 @@
#include "Page.h"
#include "ShadowRoot.h"
#include "TreeScopeAdopter.h"
+#include <wtf/Vector.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/CString.h>
@@ -231,5 +232,38 @@
return node;
}
+static void listTreeScopes(Node* node, Vector<TreeScope*, 5>& treeScopes)
+{
+ while (true) {
+ treeScopes.append(node->treeScope());
+ Node* ancestor = node->shadowAncestorNode();
+ if (node == ancestor)
+ break;
+ node = ancestor;
+ }
+}
+
+TreeScope* commonTreeScope(Node* nodeA, Node* nodeB)
+{
+ if (!nodeA || !nodeB)
+ return 0;
+
+ if (nodeA->treeScope() == nodeB->treeScope())
+ return nodeA->treeScope();
+
+ Vector<TreeScope*, 5> treeScopesA;
+ listTreeScopes(nodeA, treeScopesA);
+
+ Vector<TreeScope*, 5> treeScopesB;
+ listTreeScopes(nodeB, treeScopesB);
+
+ size_t indexA = treeScopesA.size();
+ size_t indexB = treeScopesB.size();
+
+ for (; indexA > 0 && indexB > 0 && treeScopesA[indexA - 1] == treeScopesB[indexB - 1]; --indexA, --indexB) { }
+
+ return treeScopesA[indexA] == treeScopesB[indexB] ? treeScopesA[indexA] : 0;
+}
+
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/TreeScope.h (118944 => 118945)
--- trunk/Source/WebCore/dom/TreeScope.h 2012-05-30 18:33:02 UTC (rev 118944)
+++ trunk/Source/WebCore/dom/TreeScope.h 2012-05-30 18:36:00 UTC (rev 118945)
@@ -110,6 +110,8 @@
return m_elementsById.containsMultiple(id.impl());
}
+TreeScope* commonTreeScope(Node*, Node*);
+
} // namespace WebCore
#endif // TreeScope_h
Modified: trunk/Source/WebCore/editing/htmlediting.cpp (118944 => 118945)
--- trunk/Source/WebCore/editing/htmlediting.cpp 2012-05-30 18:33:02 UTC (rev 118944)
+++ trunk/Source/WebCore/editing/htmlediting.cpp 2012-05-30 18:36:00 UTC (rev 118945)
@@ -72,32 +72,28 @@
// could be inside a shadow tree. Only works for non-null values.
int comparePositions(const Position& a, const Position& b)
{
- Node* nodeA = a.deprecatedNode();
+ TreeScope* commonScope = commonTreeScope(a.containerNode(), b.containerNode());
+
+ ASSERT(commonScope);
+ if (!commonScope)
+ return 0;
+
+ Node* nodeA = commonScope->ancestorInThisScope(a.deprecatedNode());
ASSERT(nodeA);
- Node* nodeB = b.deprecatedNode();
+ bool hasDescendentA = nodeA != a.deprecatedNode();
+ int offsetA = hasDescendentA ? 0 : a.deprecatedEditingOffset();
+
+ Node* nodeB = commonScope->ancestorInThisScope(b.deprecatedNode());
ASSERT(nodeB);
- int offsetA = a.deprecatedEditingOffset();
- int offsetB = b.deprecatedEditingOffset();
+ bool hasDescendentB = nodeB != b.deprecatedNode();
+ int offsetB = hasDescendentB ? 0 : b.deprecatedEditingOffset();
- Node* shadowAncestorA = nodeA->shadowAncestorNode();
- if (shadowAncestorA == nodeA)
- shadowAncestorA = 0;
- Node* shadowAncestorB = nodeB->shadowAncestorNode();
- if (shadowAncestorB == nodeB)
- shadowAncestorB = 0;
-
int bias = 0;
- if (shadowAncestorA != shadowAncestorB) {
- if (shadowAncestorA) {
- nodeA = shadowAncestorA;
- offsetA = 0;
- bias = 1;
- }
- if (shadowAncestorB) {
- nodeB = shadowAncestorB;
- offsetB = 0;
+ if (nodeA == nodeB) {
+ if (hasDescendentA)
bias = -1;
- }
+ else if (hasDescendentB)
+ bias = 1;
}
ExceptionCode ec;