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 + " ";
+ 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;
};