Title: [117249] trunk
Revision
117249
Author
[email protected]
Date
2012-05-16 03:08:23 -0700 (Wed, 16 May 2012)

Log Message

ShadowRoot.selection should return the seleciton whose range is in a shadow tree.
https://bugs.webkit.org/show_bug.cgi?id=82698

Reviewed by Ryosuke Niwa.

Source/WebCore:

The selection object returned from shadowRoot.selection should be able to see
the inner object of the shadowRoot.

In the previous code, the node out of the shadow subtree was returned for
anchorNode, focusNode, baseNode, and extentNode. This patch enables us to get
the corresponding shadow ancestor in the specified TreeScope (m_treeScope).

Tests: editing/shadow/selection-of-orphan-shadowroot.html
       editing/shadow/selection-of-shadowroot.html

* dom/ShadowRoot.cpp:
(WebCore::ShadowRoot::selection):
* dom/ShadowRoot.h:
(ShadowRoot):
* dom/TreeScope.cpp:
(WebCore::TreeScope::getSelection): When shadow DOM feature is not enabled, we want to use the same
instance of DOMSelection among Document and ShadowRoot.
* dom/TreeScopeAdjuster.cpp:
(WebCore::TreeScopeAdjuster::TreeScopeAdjuster):
(WebCore::TreeScopeAdjuster::ancestorInThisScope): Since node could be null, I've added a node check code.
* dom/TreeScopeAdjuster.h:
(TreeScopeAdjuster):
(WebCore::TreeScopeAdjuster::treeScope):
* page/DOMSelection.cpp:
(WebCore::DOMSelection::anchorNode):
(WebCore::DOMSelection::anchorOffset):
(WebCore::DOMSelection::focusNode):
(WebCore::DOMSelection::focusOffset):
(WebCore::DOMSelection::baseNode):
(WebCore::DOMSelection::baseOffset):
(WebCore::DOMSelection::extentNode):
(WebCore::DOMSelection::extentOffset):
(WebCore::DOMSelection::shadowAdjustedNode): Gets the corresponding node in the m_treeScope from the Position.
(WebCore):
(WebCore::DOMSelection::shadowAdjustedOffset): Gets the corresponding node offset in the m_treeScope from the Position.
* page/DOMSelection.h:
(WebCore):
(DOMSelection):

LayoutTests:

This patch contains 2 tests:
- Generates a complex HTML tree having a ShadowRoot, an older ShadowRoot, a nested ShadowRoot,
nested ShadowRoot in an older ShadowRoot, etc., and try to drag from a nested shadow root of
older shadow root to a nested shadow root of younger shadow root. Then checks nodes of Shadowroot.selection
are in the same tree scope or null.
- Generates a ShadowDOM which is not inserted into a document, and confirms nodes taken from
the selection are all null.

Also, this patch deprecates old shadowRoot.selection tests, because they test to check
window.getSelection() and shadowRoot.selection is the same. This behavior is changed by this patch.

* editing/shadow/selection-of-orphan-shadowroot-expected.txt: Added.
* editing/shadow/selection-of-orphan-shadowroot.html: Added.
* editing/shadow/selection-of-shadowroot-expected.txt: Added.
* editing/shadow/selection-of-shadowroot.html: Added.
* fast/dom/resources/event-sender-util.js:
(mouseMoveToElem):
(dragFromTo):
* fast/dom/shadow/resources/shadow-dom-util.js: Added.
(getElementByIdConsideringShadowDOM.iter):
(getElementByIdConsideringShadowDOM):
* fast/dom/shadow/selection-in-shadow.html: Removed.
* platform/chromium-mac-snowleopard/fast/dom/shadow/selection-in-shadow-expected.txt: Removed.
* platform/chromium/fast/dom/shadow/selection-in-shadow-expected.txt: Removed.
* platform/qt/Skipped:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (117248 => 117249)


--- trunk/LayoutTests/ChangeLog	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/LayoutTests/ChangeLog	2012-05-16 10:08:23 UTC (rev 117249)
@@ -1,3 +1,36 @@
+2012-05-16  Shinya Kawanaka  <[email protected]>
+
+        ShadowRoot.selection should return the seleciton whose range is in a shadow tree.
+        https://bugs.webkit.org/show_bug.cgi?id=82698
+
+        Reviewed by Ryosuke Niwa.
+
+        This patch contains 2 tests:
+        - Generates a complex HTML tree having a ShadowRoot, an older ShadowRoot, a nested ShadowRoot,
+        nested ShadowRoot in an older ShadowRoot, etc., and try to drag from a nested shadow root of
+        older shadow root to a nested shadow root of younger shadow root. Then checks nodes of Shadowroot.selection
+        are in the same tree scope or null.
+        - Generates a ShadowDOM which is not inserted into a document, and confirms nodes taken from
+        the selection are all null.
+
+        Also, this patch deprecates old shadowRoot.selection tests, because they test to check
+        window.getSelection() and shadowRoot.selection is the same. This behavior is changed by this patch.
+
+        * editing/shadow/selection-of-orphan-shadowroot-expected.txt: Added.
+        * editing/shadow/selection-of-orphan-shadowroot.html: Added.
+        * editing/shadow/selection-of-shadowroot-expected.txt: Added.
+        * editing/shadow/selection-of-shadowroot.html: Added.
+        * fast/dom/resources/event-sender-util.js:
+        (mouseMoveToElem):
+        (dragFromTo):
+        * fast/dom/shadow/resources/shadow-dom-util.js: Added.
+        (getElementByIdConsideringShadowDOM.iter):
+        (getElementByIdConsideringShadowDOM):
+        * fast/dom/shadow/selection-in-shadow.html: Removed.
+        * platform/chromium-mac-snowleopard/fast/dom/shadow/selection-in-shadow-expected.txt: Removed.
+        * platform/chromium/fast/dom/shadow/selection-in-shadow-expected.txt: Removed.
+        * platform/qt/Skipped:
+
 2012-05-16  Andras Becsi  <[email protected]>
 
         [WTR] Visited link tracking is not disabled properly

Added: trunk/LayoutTests/editing/shadow/selection-of-orphan-shadowroot-expected.txt (0 => 117249)


--- trunk/LayoutTests/editing/shadow/selection-of-orphan-shadowroot-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/shadow/selection-of-orphan-shadowroot-expected.txt	2012-05-16 10:08:23 UTC (rev 117249)
@@ -0,0 +1,10 @@
+Nodes of the selection for orphan shadow root should return null.
+
+PASS selection.anchorNode is null
+PASS selection.focusNode is null
+PASS selection.baseNode is null
+PASS selection.extentNode is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/editing/shadow/selection-of-orphan-shadowroot.html (0 => 117249)


--- trunk/LayoutTests/editing/shadow/selection-of-orphan-shadowroot.html	                        (rev 0)
+++ trunk/LayoutTests/editing/shadow/selection-of-orphan-shadowroot.html	2012-05-16 10:08:23 UTC (rev 117249)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+
+<p>Nodes of the selection for an orphan shadow root should return null.</p>
+
+<pre id="console"></pre>
+
+<script>
+var host = document.createElement('div');
+var shadowRoot = new WebKitShadowRoot(host);
+shadowRoot.innerHTML = "Kotori Otonashi"
+
+var selection = shadowRoot.selection;
+
+shouldBe('selection.anchorNode', 'null');
+shouldBe('selection.focusNode', 'null');
+shouldBe('selection.baseNode', 'null');
+shouldBe('selection.extentNode', 'null');
+
+var successfullyParsed = true;
+</script>
+<script src=""
+</body>
+
+</html>

Added: trunk/LayoutTests/editing/shadow/selection-of-shadowroot-expected.txt (0 => 117249)


--- trunk/LayoutTests/editing/shadow/selection-of-shadowroot-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/editing/shadow/selection-of-shadowroot-expected.txt	2012-05-16 10:08:23 UTC (rev 117249)
@@ -0,0 +1,46 @@
+In this test, we create a complex Shadow DOM and try to drag from a div in nested shadow root of older shadow root to a div in nested shadow root of younger shadow root. Then we get selection from the following TreeScopes:
+ * treeScopes[0] = document
+ * treeScopes[1] = OLDER SHADOW ROOT
+ * treeScopes[2] = YOUNGER SHADOW ROOT
+ * treeScopes[3] = NESTED SHADOW ROOT IN OLDER SHADOW ROOT
+ * treeScopes[4] = NESTED SHADOW ROOT IN YOUNGER SHADOW ROOT
+and check selection.anchorNode, selection.focusNode, selection.baseNode, and selection.extentNode are null or in the same treescope.
+
+Dragged from (DIV 2 IN NESTED SHADOW DOM OF OLDER SHADOW ROOT) to (DIV 2 IN NESTED SHADOW DOM OF YOUNGER SHADOW ROOT)
+
+treeScopes[0] is document
+PASS internals.treeScopeRootNode(treeScopes[0].getSelection().anchorNode) is document
+PASS internals.treeScopeRootNode(treeScopes[0].getSelection().focusNode) is document
+PASS internals.treeScopeRootNode(treeScopes[0].getSelection().baseNode) is document
+PASS internals.treeScopeRootNode(treeScopes[0].getSelection().extentNode) is document
+
+treeScopes[1] is OLDER SHADOW ROOT
+PASS internals.treeScopeRootNode(treeScopes[1].getSelection().anchorNode) is treeScopes[1]
+PASS internals.treeScopeRootNode(treeScopes[1].getSelection().focusNode) is treeScopes[1]
+PASS internals.treeScopeRootNode(treeScopes[1].getSelection().baseNode) is treeScopes[1]
+PASS internals.treeScopeRootNode(treeScopes[1].getSelection().extentNode) is treeScopes[1]
+
+treeScopes[2] is YOUNGER SHADOW ROOT
+Since treeScope[2] is outside of selection start point, no node should not be taken.
+PASS treeScopes[2].getSelection().anchorNode is null
+PASS treeScopes[2].getSelection().focusNode is null
+PASS treeScopes[2].getSelection().baseNode is null
+PASS treeScopes[2].getSelection().extentNode is null
+
+treeScopes[3] is NESTED SHADOW ROOT IN OLDER SHADOW ROOT
+PASS internals.treeScopeRootNode(treeScopes[3].getSelection().anchorNode) is treeScopes[3]
+PASS internals.treeScopeRootNode(treeScopes[3].getSelection().focusNode) is treeScopes[3]
+PASS internals.treeScopeRootNode(treeScopes[3].getSelection().baseNode) is treeScopes[3]
+PASS internals.treeScopeRootNode(treeScopes[3].getSelection().extentNode) is treeScopes[3]
+
+treeScopes[4] is NESTED SHADOW ROOT IN YOUNGER SHADOW ROOT
+Since treeScope[4] is outside of selection start point, no node should not be taken.
+PASS treeScopes[4].getSelection().anchorNode is null
+PASS treeScopes[4].getSelection().focusNode is null
+PASS treeScopes[4].getSelection().baseNode is null
+PASS treeScopes[4].getSelection().extentNode is null
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/editing/shadow/selection-of-shadowroot.html (0 => 117249)


--- trunk/LayoutTests/editing/shadow/selection-of-shadowroot.html	                        (rev 0)
+++ trunk/LayoutTests/editing/shadow/selection-of-shadowroot.html	2012-05-16 10:08:23 UTC (rev 117249)
@@ -0,0 +1,142 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>selection-of-shadowroot</title>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+
+<div id="container"></div>
+<pre id="console"></pre>
+
+<script>
+var treeScopes = new Array();
+treeScopes.push(document);
+
+function indent(level) {
+    var v = "";
+    while (level--)
+        v = v + "&nbsp;&nbsp;&nbsp;&nbsp;";
+    return v;
+}
+
+function createComplexShadowTree(container) {
+    function createInnerShadowDOM(shadowRoot, id, name, indentLevel) {
+        shadowRoot.innerHTML = 
+            "<div title='DIV1 IN " + name + "'>" + indent(indentLevel) + "DIV 1 (" + name + ")</div>" +
+            "<div>" + indent(indentLevel) + "<div title='SHADOW HOST IN " + name + "'>DIV HOST (" + name + ")</div></div>" +
+            "<div title='DIV2 IN " + name + "'>" + indent(indentLevel) + "DIV 2 (" + name + ")</div>" +
+            "<shadow>SHADOW FALLBACK</shadow>" +
+            "<div title='DIV3 IN " + name + "'>" + indent(indentLevel) + "DIV 3 (" + name + ")</div>";
+
+        var hostInShadowRoot = shadowRoot.firstChild.nextSibling;
+        var nestedShadowRoot = new WebKitShadowRoot(hostInShadowRoot);
+        nestedShadowRoot.title = 'NESTED SHADOW ROOT IN ' + name;
+        treeScopes.push(nestedShadowRoot);
+
+        nestedShadowRoot.innerHTML =
+            "<div title='DIV 1 IN NESTED SHADOW DOM OF " + name + "'>" + indent(indentLevel) + "DIV 1 IN NESTED SHADOW (" + name + ")</div>" + 
+            "<shadow>NESTED SHADOW FALLBACK</shadow>" + 
+            "<div id='" + id + "' title='DIV 2 IN NESTED SHADOW DOM OF " + name + "'>" + indent(indentLevel) + "DIV 2 IN NESTED SHADOW (" + name + ")</div>";
+    }
+
+    container.innerHTML = 
+        "<div title='DIV BEFORE HOST ELEMENT'>BEFORE HOST</div>" +
+        "<div><div title='HOST ELEMENT'>HOST</div></div>" +
+        "<div title='DIV AFTER HOST ELEMENT'>AFTER HOST</div>";
+
+    var host = container.firstChild.nextSibling;
+
+    var olderShadowRoot = new WebKitShadowRoot(host);
+    olderShadowRoot.title = 'OLDER SHADOW ROOT';
+    treeScopes.push(olderShadowRoot);
+
+    var youngerShadowRoot = new WebKitShadowRoot(host);
+    youngerShadowRoot.title = 'YOUNGER SHADOW ROOT';
+    treeScopes.push(youngerShadowRoot);
+
+    createInnerShadowDOM(olderShadowRoot, 'older', 'OLDER SHADOW ROOT', 2);
+    createInnerShadowDOM(youngerShadowRoot, 'younger', 'YOUNGER SHADOW ROOT', 1);
+}
+
+var container = document.getElementById('container');
+createComplexShadowTree(container);
+
+for (var k = 0; k < treeScopes.length; ++k) {
+    if (!treeScopes[k].getSelection) {
+        treeScopes[k].getSelection = (function(self, k) {
+            return function() { return self.selection; }
+        })(treeScopes[k], k);
+    }
+}
+
+debug('In this test, we create a complex Shadow DOM and try to drag from a div in nested shadow root of older shadow root to a div in nested shadow root of younger shadow root. Then we get selection from the following TreeScopes:');
+for (var k = 0; k < treeScopes.length; ++k) {
+    if (treeScopes[k] == document)
+        debug(" * treeScopes[" + k + "] = document");
+    else
+        debug(" * treeScopes[" + k + "] = " + treeScopes[k].title);
+}
+
+debug('and check selection.anchorNode, selection.focusNode, selection.baseNode, and selection.extentNode are null or in the same treescope.');
+debug('');
+
+var older = getElementByIdConsideringShadowDOM(document, 'older');
+var younger = getElementByIdConsideringShadowDOM(document, 'younger');
+dragFromTo(older, younger);
+
+debug('Dragged from (' + older.title + ') to (' + younger.title + ')');
+debug('');
+
+debug("treeScopes[0] is document");
+shouldBe("internals.treeScopeRootNode(treeScopes[0].getSelection().anchorNode)", "document");
+shouldBe("internals.treeScopeRootNode(treeScopes[0].getSelection().focusNode)", "document");
+shouldBe("internals.treeScopeRootNode(treeScopes[0].getSelection().baseNode)", "document");
+shouldBe("internals.treeScopeRootNode(treeScopes[0].getSelection().extentNode)", "document");
+debug('');
+
+debug("treeScopes[1] is " + treeScopes[1].title);
+shouldBe("internals.treeScopeRootNode(treeScopes[1].getSelection().anchorNode)", "treeScopes[1]");
+shouldBe("internals.treeScopeRootNode(treeScopes[1].getSelection().focusNode)", "treeScopes[1]");
+shouldBe("internals.treeScopeRootNode(treeScopes[1].getSelection().baseNode)", "treeScopes[1]");
+shouldBe("internals.treeScopeRootNode(treeScopes[1].getSelection().extentNode)", "treeScopes[1]");
+debug('');
+
+debug("treeScopes[2] is " + treeScopes[2].title);
+debug('Since treeScope[2] is outside of selection start point, no node should not be taken.');
+shouldBe("treeScopes[2].getSelection().anchorNode", "null");
+shouldBe("treeScopes[2].getSelection().focusNode", "null");
+shouldBe("treeScopes[2].getSelection().baseNode", "null");
+shouldBe("treeScopes[2].getSelection().extentNode", "null");
+debug('');
+
+debug("treeScopes[3] is " + treeScopes[3].title);
+shouldBe("internals.treeScopeRootNode(treeScopes[3].getSelection().anchorNode)", "treeScopes[3]");
+shouldBe("internals.treeScopeRootNode(treeScopes[3].getSelection().focusNode)", "treeScopes[3]");
+shouldBe("internals.treeScopeRootNode(treeScopes[3].getSelection().baseNode)", "treeScopes[3]");
+shouldBe("internals.treeScopeRootNode(treeScopes[3].getSelection().extentNode)", "treeScopes[3]");
+debug('');
+
+debug("treeScopes[4] is " + treeScopes[4].title);
+debug('Since treeScope[4] is outside of selection start point, no node should not be taken.');
+shouldBe("treeScopes[4].getSelection().anchorNode", "null");
+shouldBe("treeScopes[4].getSelection().focusNode", "null");
+shouldBe("treeScopes[4].getSelection().baseNode", "null");
+shouldBe("treeScopes[4].getSelection().extentNode", "null");
+debug('');
+
+window.getSelection().removeAllRanges();
+
+while (container.firstChild)
+    container.removeChild(container.firstChild);
+
+var successfullyParsed = true;
+</script>
+<script src=""
+</body>
+
+</html>

Modified: trunk/LayoutTests/fast/dom/resources/event-sender-util.js (117248 => 117249)


--- trunk/LayoutTests/fast/dom/resources/event-sender-util.js	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/LayoutTests/fast/dom/resources/event-sender-util.js	2012-05-16 10:08:23 UTC (rev 117249)
@@ -1,8 +1,23 @@
 //----------------------------------------------------------------------
 // _javascript_ Library to utilize eventSender conveniently
 
-function mouseMoveToElem(element) {
-    var x = element.offsetLeft + element.offsetWidth / 2;
+function mouseMoveToElem(element, pos) {
+    var x = element.offsetLeft;
     var y = element.offsetTop + element.offsetHeight / 2;
+
+    if (pos == 'left')
+        x += element.offsetWidth / 4;
+    else if (pos == 'right')
+        x += element.offsetWidth * 3 / 4;
+    else
+        x += element.offsetWidth / 2;
+
     eventSender.mouseMoveTo(x, y);
+}
+
+function dragFromTo(elementFrom, elementTo) {
+    mouseMoveToElem(elementFrom, 'left');
+    eventSender.mouseDown();
+    mouseMoveToElem(elementTo, 'right');
+    eventSender.mouseUp();
 }
\ No newline at end of file

Added: trunk/LayoutTests/fast/dom/shadow/resources/shadow-dom-util.js (0 => 117249)


--- trunk/LayoutTests/fast/dom/shadow/resources/shadow-dom-util.js	                        (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/resources/shadow-dom-util.js	2012-05-16 10:08:23 UTC (rev 117249)
@@ -0,0 +1,35 @@
+// ----------------------------------------------------------------------
+// shadow-dom-util.js is a set of utility to test Shadow DOM.
+
+function getElementByIdConsideringShadowDOM(root, id) {
+    function iter(root, id) {
+        if (!root)
+            return null;
+
+        if (root.id == id)
+            return root;
+
+        // We don't collect div having a shadow root, since we cannot point it correctly.
+        // Such div should have an inner div to be pointed correctly.
+        for (var child = root.firstChild; child; child = child.nextSibling) {
+            var node = iter(child, id);
+            if (node != null)
+                return node;
+        }
+
+        if (root.nodeType != 1)
+            return null;
+
+        for (var shadowRoot = internals.youngestShadowRoot(root); shadowRoot; shadowRoot = internals.olderShadowRoot(shadowRoot)) {
+            var node = iter(shadowRoot, id);
+            if (node != null)
+                return node;
+        }
+
+        return null;
+    };
+
+    if (!window.internals)
+        return null;
+    return iter(root, id);
+}

Deleted: trunk/LayoutTests/fast/dom/shadow/selection-in-shadow.html (117248 => 117249)


--- trunk/LayoutTests/fast/dom/shadow/selection-in-shadow.html	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/LayoutTests/fast/dom/shadow/selection-in-shadow.html	2012-05-16 10:08:23 UTC (rev 117249)
@@ -1,78 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script src=""
-<script src=""
-</head>
-<body>
-
-<div id="container"></div>
-
-<script>
-function moveTo(element) {
-    var x = element.offsetLeft + element.offsetWidth / 2;
-    var y = element.offsetTop + element.offsetHeight / 2;
-    eventSender.mouseMoveTo(x, y);
-}
-
-function dragFromTo(elementFrom, elementTo) {
-    moveTo(elementFrom);
-    eventSender.mouseDown();
-    moveTo(elementTo);
-    eventSender.mouseUp();
-}
-
-var container = document.getElementById('container');
-
-var shadowRoot1 = new WebKitShadowRoot(container);
-shadowRoot1.innerHTML =
-    '<div id="div1" title="div1">DIV1</div>' +
-    '<div id="div2" title="div2">DIV2</div>' +
-    '<div id="div3" title="div3">DIV3</div>';
-var div1 = shadowRoot1.getElementById('div1');
-var div2 = shadowRoot1.getElementById('div2');
-var div3 = shadowRoot1.getElementById('div3');
-
-var shadowRoot2 = new WebKitShadowRoot(div2);
-shadowRoot2.innerHTML =
-    '<div id="div4" title="div4">DIV4</div>' +
-    '<div id="div5" title="div5">DIV5</div>' +
-    '<div id="div6" title="div6">DIV6</div>';
-var div4 = shadowRoot2.getElementById('div4');
-var div5 = shadowRoot2.getElementById('div5');
-var div6 = shadowRoot2.getElementById('div6');
-
-var shadowRoot3 = new WebKitShadowRoot(div5);
-shadowRoot3.innerHTML =
-    '<div id="div7" title="div7">DIV7</div>' +
-    '<div id="div8" title="div8">DIV8</div>' +
-    '<div id="div9" title="div9">DIV9</div>';
-var div7 = shadowRoot3.getElementById('div7');
-var div8 = shadowRoot3.getElementById('div8');
-var div9 = shadowRoot3.getElementById('div9');
-
-
-dragFromTo(div4, div6);
-var selectionFromWindow = window.getSelection();
-var selectionFromShadowRoot1 = shadowRoot1.selection;
-var selectionFromShadowRoot2 = shadowRoot2.selection;
-var selectionFromShadowRoot3 = shadowRoot3.selection;
-
-// Since there are these bugs, shadowRoot.selection won't return the correct selection now.
-// Currently it is the same as window.getSelection().
-// FIXME: VisibleSelection in ShadowRoot is not intuitive.
-// http://wkb.ug/82683
-// FIXME: ShadowRoot.selection should return selection whose range is in a shadow tree.
-// http://wkb.ug/82698
-
-shouldBe('selectionFromWindow.anchorNode', 'selectionFromShadowRoot1.anchorNode');
-shouldBe('selectionFromWindow.anchorNode', 'selectionFromShadowRoot2.anchorNode');
-shouldBe('selectionFromWindow.anchorNode', 'selectionFromShadowRoot3.anchorNode');
-
-shouldBe('selectionFromWindow.focusNode', 'selectionFromShadowRoot1.focusNode');
-shouldBe('selectionFromWindow.focusNode', 'selectionFromShadowRoot2.focusNode');
-shouldBe('selectionFromWindow.focusNode', 'selectionFromShadowRoot3.focusNode');
-</script>
-<script src=""
-</body>
-</html>

Deleted: trunk/LayoutTests/platform/chromium/fast/dom/shadow/selection-in-shadow-expected.txt (117248 => 117249)


--- trunk/LayoutTests/platform/chromium/fast/dom/shadow/selection-in-shadow-expected.txt	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/LayoutTests/platform/chromium/fast/dom/shadow/selection-in-shadow-expected.txt	2012-05-16 10:08:23 UTC (rev 117249)
@@ -1,10 +0,0 @@
-PASS selectionFromWindow.anchorNode is selectionFromShadowRoot1.anchorNode
-PASS selectionFromWindow.anchorNode is selectionFromShadowRoot2.anchorNode
-PASS selectionFromWindow.anchorNode is selectionFromShadowRoot3.anchorNode
-PASS selectionFromWindow.focusNode is selectionFromShadowRoot1.focusNode
-PASS selectionFromWindow.focusNode is selectionFromShadowRoot2.focusNode
-PASS selectionFromWindow.focusNode is selectionFromShadowRoot3.focusNode
-PASS successfullyParsed is true
-
-TEST COMPLETE
-

Deleted: trunk/LayoutTests/platform/chromium-mac-snowleopard/fast/dom/shadow/selection-in-shadow-expected.txt (117248 => 117249)


--- trunk/LayoutTests/platform/chromium-mac-snowleopard/fast/dom/shadow/selection-in-shadow-expected.txt	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/LayoutTests/platform/chromium-mac-snowleopard/fast/dom/shadow/selection-in-shadow-expected.txt	2012-05-16 10:08:23 UTC (rev 117249)
@@ -1,10 +0,0 @@
-PASS selectionFromWindow.anchorNode is selectionFromShadowRoot1.anchorNode
-PASS selectionFromWindow.anchorNode is selectionFromShadowRoot2.anchorNode
-PASS selectionFromWindow.anchorNode is selectionFromShadowRoot3.anchorNode
-PASS selectionFromWindow.focusNode is selectionFromShadowRoot1.focusNode
-PASS selectionFromWindow.focusNode is selectionFromShadowRoot2.focusNode
-PASS selectionFromWindow.focusNode is selectionFromShadowRoot3.focusNode
-PASS successfullyParsed is true
-
-TEST COMPLETE
-

Modified: trunk/LayoutTests/platform/qt/Skipped (117248 => 117249)


--- trunk/LayoutTests/platform/qt/Skipped	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/LayoutTests/platform/qt/Skipped	2012-05-16 10:08:23 UTC (rev 117249)
@@ -187,7 +187,6 @@
 fast/dom/shadow/multiple-shadowroot-rendering.html
 fast/dom/shadow/multiple-shadowroot-adopt.html
 fast/dom/shadow/selections-in-shadow.html
-fast/dom/shadow/selection-in-shadow.html
 fast/dom/shadow/selection-shouldnt-expose-shadow-dom.html
 fast/dom/shadow/shadow-boundary-events.html
 fast/dom/shadow/shadow-content-crash.html

Modified: trunk/Source/WebCore/ChangeLog (117248 => 117249)


--- trunk/Source/WebCore/ChangeLog	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/Source/WebCore/ChangeLog	2012-05-16 10:08:23 UTC (rev 117249)
@@ -1,3 +1,49 @@
+2012-05-16  Shinya Kawanaka  <[email protected]>
+
+        ShadowRoot.selection should return the seleciton whose range is in a shadow tree.
+        https://bugs.webkit.org/show_bug.cgi?id=82698
+
+        Reviewed by Ryosuke Niwa.
+
+        The selection object returned from shadowRoot.selection should be able to see
+        the inner object of the shadowRoot.
+
+        In the previous code, the node out of the shadow subtree was returned for
+        anchorNode, focusNode, baseNode, and extentNode. This patch enables us to get
+        the corresponding shadow ancestor in the specified TreeScope (m_treeScope).
+
+        Tests: editing/shadow/selection-of-orphan-shadowroot.html
+               editing/shadow/selection-of-shadowroot.html
+
+        * dom/ShadowRoot.cpp:
+        (WebCore::ShadowRoot::selection):
+        * dom/ShadowRoot.h:
+        (ShadowRoot):
+        * dom/TreeScope.cpp:
+        (WebCore::TreeScope::getSelection): When shadow DOM feature is not enabled, we want to use the same
+        instance of DOMSelection among Document and ShadowRoot.
+        * dom/TreeScopeAdjuster.cpp:
+        (WebCore::TreeScopeAdjuster::TreeScopeAdjuster):
+        (WebCore::TreeScopeAdjuster::ancestorInThisScope): Since node could be null, I've added a node check code.
+        * dom/TreeScopeAdjuster.h:
+        (TreeScopeAdjuster):
+        (WebCore::TreeScopeAdjuster::treeScope):
+        * page/DOMSelection.cpp:
+        (WebCore::DOMSelection::anchorNode):
+        (WebCore::DOMSelection::anchorOffset):
+        (WebCore::DOMSelection::focusNode):
+        (WebCore::DOMSelection::focusOffset):
+        (WebCore::DOMSelection::baseNode):
+        (WebCore::DOMSelection::baseOffset):
+        (WebCore::DOMSelection::extentNode):
+        (WebCore::DOMSelection::extentOffset):
+        (WebCore::DOMSelection::shadowAdjustedNode): Gets the corresponding node in the m_treeScope from the Position.
+        (WebCore):
+        (WebCore::DOMSelection::shadowAdjustedOffset): Gets the corresponding node offset in the m_treeScope from the Position.
+        * page/DOMSelection.h:
+        (WebCore):
+        (DOMSelection):
+
 2012-05-16  Jason Liu  <[email protected]>
 
         [BlackBerry] xhr request to non existent file response is 0 and not 404.

Modified: trunk/Source/WebCore/dom/ShadowRoot.cpp (117248 => 117249)


--- trunk/Source/WebCore/dom/ShadowRoot.cpp	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/Source/WebCore/dom/ShadowRoot.cpp	2012-05-16 10:08:23 UTC (rev 117249)
@@ -149,11 +149,9 @@
         replaceChildrenWithFragment(this, fragment.release(), ec);
 }
 
-DOMSelection* ShadowRoot::selection()
+DOMSelection* ShadowRoot::selection() const
 {
-    if (document())
-        return document()->getSelection();
-    return 0;
+    return getSelection();
 }
 
 bool ShadowRoot::childTypeAllowed(NodeType type) const

Modified: trunk/Source/WebCore/dom/ShadowRoot.h (117248 => 117249)


--- trunk/Source/WebCore/dom/ShadowRoot.h	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/Source/WebCore/dom/ShadowRoot.h	2012-05-16 10:08:23 UTC (rev 117249)
@@ -76,7 +76,7 @@
 
     Element* activeElement() const;
 
-    DOMSelection* selection();
+    DOMSelection* selection() const;
 
     ShadowRoot* youngerShadowRoot() const { return prev(); }
     ShadowRoot* olderShadowRoot() const { return next(); }

Modified: trunk/Source/WebCore/dom/TreeScope.cpp (117248 => 117249)


--- trunk/Source/WebCore/dom/TreeScope.cpp	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/Source/WebCore/dom/TreeScope.cpp	2012-05-16 10:08:23 UTC (rev 117249)
@@ -38,6 +38,7 @@
 #include "HTMLMapElement.h"
 #include "HTMLNames.h"
 #include "Page.h"
+#include "RuntimeEnabledFeatures.h"
 #include "TreeScopeAdopter.h"
 #include <wtf/text/AtomicString.h>
 #include <wtf/text/CString.h>
@@ -130,6 +131,19 @@
     if (m_selection)
         return m_selection.get();
 
+    // FIXME: The correct selection in Shadow DOM requires that Position can have a ShadowRoot
+    // as a container. It is now enabled only if runtime Shadow DOM feature is enabled.
+    // See https://bugs.webkit.org/show_bug.cgi?id=82697
+#if ENABLE(SHADOW_DOM)
+    if (RuntimeEnabledFeatures::shadowDOMEnabled()) {
+        m_selection = DOMSelection::create(this);
+        return m_selection.get();
+    }
+#endif
+
+    if (this != rootNode()->document())
+        return rootNode()->document()->getSelection();
+
     m_selection = DOMSelection::create(rootNode()->document());
     return m_selection.get();
 }

Modified: trunk/Source/WebCore/dom/TreeScopeAdjuster.cpp (117248 => 117249)


--- trunk/Source/WebCore/dom/TreeScopeAdjuster.cpp	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/Source/WebCore/dom/TreeScopeAdjuster.cpp	2012-05-16 10:08:23 UTC (rev 117249)
@@ -31,19 +31,20 @@
 
 namespace WebCore {
 
-TreeScopeAdjuster::TreeScopeAdjuster(TreeScope* treeScope)
+TreeScopeAdjuster::TreeScopeAdjuster(const TreeScope* treeScope)
     : m_treeScope(treeScope)
 {
 }
 
 Node* TreeScopeAdjuster::ancestorInThisScope(Node* node)
 {
-    do {
+    while (node) {
         if (node->treeScope() == treeScope())
             return node;
         if (!node->isInShadowTree())
             return 0;
-    } while ((node = node->shadowAncestorNode()));
+        node = node->shadowAncestorNode();
+    }
 
     return 0;
 }

Modified: trunk/Source/WebCore/dom/TreeScopeAdjuster.h (117248 => 117249)


--- trunk/Source/WebCore/dom/TreeScopeAdjuster.h	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/Source/WebCore/dom/TreeScopeAdjuster.h	2012-05-16 10:08:23 UTC (rev 117249)
@@ -35,9 +35,9 @@
 
 class TreeScopeAdjuster {
 public:
-    explicit TreeScopeAdjuster(TreeScope*);
+    explicit TreeScopeAdjuster(const TreeScope*);
 
-    inline TreeScope* treeScope() const { return m_treeScope; }
+    inline const TreeScope* treeScope() const { return m_treeScope; }
 
     Node* ancestorInThisScope(Node*);
 
@@ -45,7 +45,7 @@
     Position adjustPositionAfter(const Position&);
 
 private:
-    TreeScope* m_treeScope;
+    const TreeScope* m_treeScope;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/page/DOMSelection.cpp (117248 => 117249)


--- trunk/Source/WebCore/page/DOMSelection.cpp	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/Source/WebCore/page/DOMSelection.cpp	2012-05-16 10:08:23 UTC (rev 117249)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Google Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -39,6 +40,7 @@
 #include "Range.h"
 #include "TextIterator.h"
 #include "TreeScope.h"
+#include "TreeScopeAdjuster.h"
 #include "htmlediting.h"
 
 namespace WebCore {
@@ -101,72 +103,64 @@
 {
     if (!m_frame)
         return 0;
-    if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
-        return shadowAncestor->parentNodeGuaranteedHostFree();
-    return anchorPosition(visibleSelection()).containerNode();
+
+    return shadowAdjustedNode(anchorPosition(visibleSelection()));
 }
 
 int DOMSelection::anchorOffset() const
 {
     if (!m_frame)
         return 0;
-    if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
-        return shadowAncestor->nodeIndex();
-    return anchorPosition(visibleSelection()).offsetInContainerNode();
+
+    return shadowAdjustedOffset(anchorPosition(visibleSelection()));
 }
 
 Node* DOMSelection::focusNode() const
 {
     if (!m_frame)
         return 0;
-    if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
-        return shadowAncestor->parentNodeGuaranteedHostFree();
-    return focusPosition(visibleSelection()).containerNode();
+
+    return shadowAdjustedNode(focusPosition(visibleSelection()));
 }
 
 int DOMSelection::focusOffset() const
 {
     if (!m_frame)
         return 0;
-    if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
-        return shadowAncestor->nodeIndex();
-    return focusPosition(visibleSelection()).offsetInContainerNode();
+
+    return shadowAdjustedOffset(focusPosition(visibleSelection()));
 }
 
 Node* DOMSelection::baseNode() const
 {
     if (!m_frame)
         return 0;
-    if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
-        return shadowAncestor->parentNodeGuaranteedHostFree();
-    return basePosition(visibleSelection()).containerNode();
+
+    return shadowAdjustedNode(basePosition(visibleSelection()));
 }
 
 int DOMSelection::baseOffset() const
 {
     if (!m_frame)
         return 0;
-    if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
-        return shadowAncestor->nodeIndex();
-    return basePosition(visibleSelection()).offsetInContainerNode();
+
+    return shadowAdjustedOffset(basePosition(visibleSelection()));
 }
 
 Node* DOMSelection::extentNode() const
 {
     if (!m_frame)
         return 0;
-    if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
-        return shadowAncestor->parentNodeGuaranteedHostFree();
-    return extentPosition(visibleSelection()).containerNode();
+
+    return shadowAdjustedNode(extentPosition(visibleSelection()));
 }
 
 int DOMSelection::extentOffset() const
 {
     if (!m_frame)
         return 0;
-    if (Node* shadowAncestor = selectionShadowAncestor(m_frame))
-        return shadowAncestor->nodeIndex();
-    return extentPosition(visibleSelection()).offsetInContainerNode();
+
+    return shadowAdjustedOffset(extentPosition(visibleSelection()));
 }
 
 bool DOMSelection::isCollapsed() const
@@ -506,6 +500,40 @@
     return plainText(m_frame->selection()->selection().toNormalizedRange().get());
 }
 
+Node* DOMSelection::shadowAdjustedNode(const Position& position) const
+{
+    if (position.isNull())
+        return 0;
+
+    Node* containerNode = position.containerNode();
+    Node* adjustedNode = TreeScopeAdjuster(m_treeScope).ancestorInThisScope(containerNode);
+
+    if (!adjustedNode)
+        return 0;
+
+    if (containerNode == adjustedNode)
+        return containerNode;
+
+    return adjustedNode->parentNodeGuaranteedHostFree();
+}
+
+int DOMSelection::shadowAdjustedOffset(const Position& position) const
+{
+    if (position.isNull())
+        return 0;
+
+    Node* containerNode = position.containerNode();
+    Node* adjustedNode = TreeScopeAdjuster(m_treeScope).ancestorInThisScope(containerNode);
+
+    if (!adjustedNode)
+        return 0;
+
+    if (containerNode == adjustedNode)
+        return position.computeOffsetInContainerNode();
+
+    return adjustedNode->nodeIndex();
+}
+
 bool DOMSelection::isValidForPosition(Node* node) const
 {
     ASSERT(m_frame);

Modified: trunk/Source/WebCore/page/DOMSelection.h (117248 => 117249)


--- trunk/Source/WebCore/page/DOMSelection.h	2012-05-16 09:58:59 UTC (rev 117248)
+++ trunk/Source/WebCore/page/DOMSelection.h	2012-05-16 10:08:23 UTC (rev 117249)
@@ -40,6 +40,7 @@
 
     class Frame;
     class Node;
+    class Position;
     class Range;
     class TreeScope;
     class VisibleSelection;
@@ -99,6 +100,9 @@
         // Convenience method for accessors, does not NULL check m_frame.
         const VisibleSelection& visibleSelection() const;
 
+        Node* shadowAdjustedNode(const Position&) const;
+        int shadowAdjustedOffset(const Position&) const;
+
         bool isValidForPosition(Node*) const;
     };
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to