Title: [210638] branches/safari-603-branch
Revision
210638
Author
[email protected]
Date
2017-01-12 08:44:58 -0800 (Thu, 12 Jan 2017)

Log Message

Merge r210432. rdar://problem/29633667

Modified Paths

Added Paths

Diff

Modified: branches/safari-603-branch/LayoutTests/ChangeLog (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/ChangeLog	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/ChangeLog	2017-01-12 16:44:58 UTC (rev 210638)
@@ -1,3 +1,33 @@
+2017-01-12  Matthew Hanson  <[email protected]>
+
+        Merge r210432. rdar://problem/29633667
+
+    2017-01-05  Ryosuke Niwa  <[email protected]>
+
+            Finding text doesn't work across shadow boundary
+            https://bugs.webkit.org/show_bug.cgi?id=158503
+
+            Reviewed by Antti Koivisto.
+
+            Updated the existing tests per changes to use an array of find options instead of raw bit mask,
+            and added a regression test for finding text by traversing flat tree along with testing
+            window.find and execCommand('FindString', false, ~) not walking across shadow boundaries.
+
+            * editing/text-iterator/count-mark-lineboxes-expected.txt:
+            * editing/text-iterator/count-mark-lineboxes.html:
+            * editing/text-iterator/count-mark-simple-lines-expected.txt:
+            * editing/text-iterator/count-mark-simple-lines.html:
+            * editing/text-iterator/count-matches-in-form-expected.txt:
+            * editing/text-iterator/count-matches-in-form.html:
+            * editing/text-iterator/count-matches-in-frames.html:
+            * editing/text-iterator/find-string-on-flat-tree-expected.txt: Added.
+            * editing/text-iterator/find-string-on-flat-tree.html: Added.
+            * fast/text/mark-matches-broken-line-rendering.html:
+            * fast/text/mark-matches-overflow-clip.html:
+            * fast/text/mark-matches-rendering-simple-lines-expected.html:
+            * fast/text/mark-matches-rendering-simple-lines.html:
+            * fast/text/mark-matches-rendering.html:
+
 2017-01-06  Ryan Haddad  <[email protected]>
 
         Merge r210377.

Modified: branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-lineboxes-expected.txt (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-lineboxes-expected.txt	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-lineboxes-expected.txt	2017-01-12 16:44:58 UTC (rev 210638)
@@ -1,8 +1,8 @@
-PASS internals.countMatchesForText('Catilina', 23, 'mark') is 3
+PASS internals.countMatchesForText('Catilina', findOptions, 'mark') is 3
 PASS internals.markerCountForNode(text, 'all') is 3
-PASS internals.countMatchesForText('Roma', 23, 'mark') is 3
+PASS internals.countMatchesForText('Roma', findOptions, 'mark') is 3
 PASS internals.markerCountForNode(text, 'all') is 6
-PASS internals.countMatchesForText('uid', 23, 'mark') is 2
+PASS internals.countMatchesForText('uid', findOptions, 'mark') is 2
 PASS internals.markerCountForNode(text, 'all') is 8
 PASS successfullyParsed is true
 

Modified: branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-lineboxes.html (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-lineboxes.html	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-lineboxes.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -49,11 +49,12 @@
 </p>
 <script>
 var text = document.getElementById('test').firstChild;
-shouldBe("internals.countMatchesForText('Catilina', 23, 'mark')", "3");
+var findOptions = ['CaseInsensitive', 'AtWordStarts', 'TreatMedialCapitalAsWordStart', 'WrapAround'];
+shouldBe("internals.countMatchesForText('Catilina', findOptions, 'mark')", "3");
 shouldBe("internals.markerCountForNode(text, 'all')", "3");
-shouldBe("internals.countMatchesForText('Roma', 23, 'mark')", "3");
+shouldBe("internals.countMatchesForText('Roma', findOptions, 'mark')", "3");
 shouldBe("internals.markerCountForNode(text, 'all')", "6");
-shouldBe("internals.countMatchesForText('uid', 23, 'mark')", "2");
+shouldBe("internals.countMatchesForText('uid', findOptions, 'mark')", "2");
 shouldBe("internals.markerCountForNode(text, 'all')", "8");
 </script>
 <script src=""

Modified: branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-simple-lines-expected.txt (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-simple-lines-expected.txt	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-simple-lines-expected.txt	2017-01-12 16:44:58 UTC (rev 210638)
@@ -1,8 +1,8 @@
-PASS internals.countMatchesForText('Catilina', 23, 'mark') is 3
+PASS internals.countMatchesForText('Catilina', findOptions, 'mark') is 3
 PASS internals.markerCountForNode(text, 'all') is 3
-PASS internals.countMatchesForText('Roma', 23, 'mark') is 3
+PASS internals.countMatchesForText('Roma', findOptions, 'mark') is 3
 PASS internals.markerCountForNode(text, 'all') is 6
-PASS internals.countMatchesForText('uid', 23, 'mark') is 2
+PASS internals.countMatchesForText('uid', findOptions, 'mark') is 2
 PASS internals.markerCountForNode(text, 'all') is 8
 PASS successfullyParsed is true
 

Modified: branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-simple-lines.html (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-simple-lines.html	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/editing/text-iterator/count-mark-simple-lines.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -46,11 +46,12 @@
 </p>
 <script>
 var text = document.getElementById('test').firstChild;
-shouldBe("internals.countMatchesForText('Catilina', 23, 'mark')", "3");
+var findOptions = ['CaseInsensitive', 'AtWordStarts', 'TreatMedialCapitalAsWordStart', 'WrapAround'];
+shouldBe("internals.countMatchesForText('Catilina', findOptions, 'mark')", "3");
 shouldBe("internals.markerCountForNode(text, 'all')", "3");
-shouldBe("internals.countMatchesForText('Roma', 23, 'mark')", "3");
+shouldBe("internals.countMatchesForText('Roma', findOptions, 'mark')", "3");
 shouldBe("internals.markerCountForNode(text, 'all')", "6");
-shouldBe("internals.countMatchesForText('uid', 23, 'mark')", "2");
+shouldBe("internals.countMatchesForText('uid', findOptions, 'mark')", "2");
 shouldBe("internals.markerCountForNode(text, 'all')", "8");
 </script>
 <script src=""

Modified: branches/safari-603-branch/LayoutTests/editing/text-iterator/count-matches-in-form-expected.txt (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/editing/text-iterator/count-matches-in-form-expected.txt	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/editing/text-iterator/count-matches-in-form-expected.txt	2017-01-12 16:44:58 UTC (rev 210638)
@@ -1,4 +1,4 @@
-PASS internals.countMatchesForText('rule', 23, '') is 1
+PASS internals.countMatchesForText('rule', ['CaseInsensitive', 'AtWordStarts', 'TreatMedialCapitalAsWordStart', 'WrapAround'], '') is 1
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: branches/safari-603-branch/LayoutTests/editing/text-iterator/count-matches-in-form.html (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/editing/text-iterator/count-matches-in-form.html	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/editing/text-iterator/count-matches-in-form.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -3,6 +3,6 @@
 <body>
 <fieldset><input value="rule"></fieldset>
 <script>
-shouldBe("internals.countMatchesForText('rule', 23, '')", "1");
+shouldBe("internals.countMatchesForText('rule', ['CaseInsensitive', 'AtWordStarts', 'TreatMedialCapitalAsWordStart', 'WrapAround'], '')", "1");
 </script>
 <script src=""

Modified: branches/safari-603-branch/LayoutTests/editing/text-iterator/count-matches-in-frames.html (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/editing/text-iterator/count-matches-in-frames.html	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/editing/text-iterator/count-matches-in-frames.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -25,7 +25,7 @@
 
     frame.contentDocument.body.innerHTML = findString;
 
-    assert_equals(internals.countFindMatches(findString, 0, ''), shouldFindInFrame ? 2 : 1);
+    assert_equals(internals.countFindMatches(findString, [], ''), shouldFindInFrame ? 2 : 1);
 }
 
 test(function () {

Added: branches/safari-603-branch/LayoutTests/editing/text-iterator/find-string-on-flat-tree-expected.txt (0 => 210638)


--- branches/safari-603-branch/LayoutTests/editing/text-iterator/find-string-on-flat-tree-expected.txt	                        (rev 0)
+++ branches/safari-603-branch/LayoutTests/editing/text-iterator/find-string-on-flat-tree-expected.txt	2017-01-12 16:44:58 UTC (rev 210638)
@@ -0,0 +1,83 @@
+This tests finding across shadow boundaries using the flat tree.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS clearSelection(); document.execCommand('FindString', null, 'in-document'); selectedText() is '(#test-content, 0) 0 to 11'
+PASS clearSelection(); window.find('in-document'); selectedText() is '(#test-content, 0) 0 to 11'
+PASS rangeText(internals.rangeOfString('in-document', null, ['DoNotTraverseFlatTree'])) is '(#test-content, 0) 0 to 11'
+PASS rangeText(internals.rangeOfString('in-document', null, [])) is '(#test-content, 0) 0 to 11'
+PASS clearSelection(); document.execCommand('FindString', null, 'in-shadow'); selectedText() is null
+PASS clearSelection(); window.find('in-shadow'); selectedText() is null
+PASS rangeText(internals.rangeOfString('in-shadow', null, ['DoNotTraverseFlatTree'])) is null
+PASS rangeText(internals.rangeOfString('in-shadow', null, [])) is '(#shadow-root, 0) 0 to 9'
+PASS clearSelection(); document.execCommand('FindString', null, 'unslotted'); selectedText() is null
+PASS clearSelection(); window.find('unslotted'); selectedText() is null
+PASS rangeText(internals.rangeOfString('unslotted', null, ['DoNotTraverseFlatTree'])) is null
+PASS rangeText(internals.rangeOfString('unslotted', null, [])) is null
+PASS clearSelection(); document.execCommand('FindString', null, 'slotted'); selectedText() is '(#slotted-element, 0) 0 to 7'
+PASS clearSelection(); window.find('slotted'); selectedText() is '(#slotted-element, 0) 0 to 7'
+PASS rangeText(internals.rangeOfString('slotted', null, ['DoNotTraverseFlatTree'])) is '(#slotted-element, 0) 0 to 7'
+PASS rangeText(internals.rangeOfString('slotted', null, [])) is '(#slotted-element, 0) 0 to 7'
+PASS clearSelection(); document.execCommand('FindString', null, 'slotted in-document'); selectedText() is '((#slotted-element, 0), 0) to ((#test-content, 2), 12)'
+PASS clearSelection(); window.find('slotted in-document'); selectedText() is '((#slotted-element, 0), 0) to ((#test-content, 2), 12)'
+PASS rangeText(internals.rangeOfString('slotted in-document', null, ['DoNotTraverseFlatTree'])) is '((#slotted-element, 0), 0) to ((#test-content, 2), 12)'
+PASS rangeText(internals.rangeOfString('slotted in-document', null, [])) is null
+PASS clearSelection(); document.execCommand('FindString', null, 'in-shadow in-document'); selectedText() is null
+PASS clearSelection(); window.find('in-shadow in-document'); selectedText() is null
+PASS rangeText(internals.rangeOfString('in-shadow in-document', null, ['DoNotTraverseFlatTree'])) is null
+PASS rangeText(internals.rangeOfString('in-shadow in-document', null, [])) is null /* Can't return a range across shadow boundary */
+PASS setSelection(testContent, 1); document.execCommand('FindString', null, 'in-document'); selectedText() is '(#test-content, 2) 1 to 12'
+PASS setSelection(testContent, 1); window.find('in-document'); selectedText() is '(#test-content, 2) 1 to 12'
+PASS rangeText(internals.rangeOfString('in-document', range(testContent, 1), ['DoNotTraverseFlatTree'])) is '(#test-content, 2) 1 to 12'
+PASS rangeText(internals.rangeOfString('in-document', range(testContent, 1), [])) is '(#test-content, 2) 1 to 12'
+PASS setSelection(shadowRoot, 0); document.execCommand('FindString', null, 'in-document'); selectedText() is '(#test-content, 2) 1 to 12'
+PASS setSelection(shadowRoot, 0); window.find('in-document'); selectedText() is '(#test-content, 2) 1 to 12'
+PASS rangeText(internals.rangeOfString('in-document', range(shadowRoot, 0), ['DoNotTraverseFlatTree'])) is '(#test-content, 2) 1 to 12'
+PASS rangeText(internals.rangeOfString('in-document', range(shadowRoot, 0), [])) is '(#test-content, 2) 1 to 12'
+PASS setSelection(shadowRoot, 0); document.execCommand('FindString', null, 'in-shadow'); selectedText() is '#test-content 1 to 1'
+PASS setSelection(shadowRoot, 0); window.find('in-shadow'); selectedText() is '#test-content 1 to 1'
+PASS rangeText(internals.rangeOfString('in-shadow', range(shadowRoot, 0), ['DoNotTraverseFlatTree'])) is '(#shadow-root, 0) 0 to 9'
+PASS rangeText(internals.rangeOfString('in-shadow', range(shadowRoot, 0), [])) is '(#shadow-root, 0) 0 to 9'
+PASS setSelection(shadowRoot, 0); document.execCommand('FindString', null, 'slotted'); selectedText() is '(#slotted-element, 0) 0 to 7' /* Wrapped around */
+PASS setSelection(shadowRoot, 0); window.find('slotted'); selectedText() is '#test-content 1 to 1'
+PASS setSelection(shadowRoot, 0); window.find('slotted', /* caseSensitive */ true, /* backwards */ false, /* wrap */ true); selectedText() is '(#slotted-element, 0) 0 to 7'
+PASS rangeText(internals.rangeOfString('slotted', range(shadowRoot, 0), ['DoNotTraverseFlatTree'])) is null
+PASS rangeText(internals.rangeOfString('slotted', range(shadowRoot, 0), [])) is '(#slotted-element, 0) 0 to 7'
+PASS setSelection(shadowRoot, 1); document.execCommand('FindString', null, 'slotted'); selectedText() is '(#slotted-element, 0) 0 to 7' /* Wrapped around */
+PASS setSelection(shadowRoot, 1); window.find('slotted'); selectedText() is '#test-content 1 to 1'
+PASS setSelection(shadowRoot, 1); window.find('slotted', /* caseSensitive */ true, /* backwards */ false, /* wrap */ true); selectedText() is '(#slotted-element, 0) 0 to 7'
+PASS rangeText(internals.rangeOfString('slotted', range(shadowRoot, 1), ['DoNotTraverseFlatTree'])) is null
+PASS rangeText(internals.rangeOfString('slotted', range(shadowRoot, 1), [])) is '(#slotted-element, 0) 0 to 7'
+PASS setSelection(shadowRoot, 1); document.execCommand('FindString', null, 'in-shadow'); selectedText() is '#test-content 1 to 1'
+PASS setSelection(shadowRoot, 1); window.find('in-shadow'); selectedText() is '#test-content 1 to 1'
+PASS rangeText(internals.rangeOfString('in-shadow', range(shadowRoot, 1), ['DoNotTraverseFlatTree'])) is '(#shadow-root, 2) 1 to 10'
+PASS rangeText(internals.rangeOfString('in-shadow', range(shadowRoot, 1), [])) is '(#shadow-root, 2) 1 to 10'
+PASS setSelection(shadowRoot, 1); document.execCommand('FindString', null, 'in-document'); selectedText() is '(#test-content, 2) 1 to 12'
+PASS setSelection(shadowRoot, 1); window.find('in-document'); selectedText() is '(#test-content, 2) 1 to 12'
+PASS rangeText(internals.rangeOfString('in-document', range(shadowRoot, 1), ['DoNotTraverseFlatTree'])) is '(#test-content, 2) 1 to 12'
+PASS rangeText(internals.rangeOfString('in-document', range(shadowRoot, 1), [])) is '(#test-content, 2) 1 to 12'
+PASS setSelection(shadowRoot, 1); document.execCommand('FindString', null, 'in-slot'); selectedText() is '#test-content 1 to 1'
+PASS setSelection(shadowRoot, 1); window.find('in-slot'); selectedText() is '#test-content 1 to 1'
+PASS rangeText(internals.rangeOfString('in-slot', range(shadowRoot, 1), ['DoNotTraverseFlatTree'])) is null
+PASS rangeText(internals.rangeOfString('in-slot', range(shadowRoot, 1), [])) is null
+PASS clearSelection(); document.execCommand('FindString', null, 'in-user-agent-shadow'); selectedText() is null
+PASS clearSelection(); window.find('in-user-agent-shadow'); selectedText() is null
+PASS rangeText(internals.rangeOfString('in-user-agent-shadow', null, ['DoNotTraverseFlatTree'])) is null
+PASS rangeText(internals.rangeOfString('in-user-agent-shadow', null, [])) is null
+PASS setSelection(userAgentShadowRoot, 0); document.execCommand('FindString', null, 'in-user-agent-shadow'); selectedText() is '#test-content 3 to 3'
+PASS setSelection(userAgentShadowRoot, 0); window.find('in-user-agent-shadow'); selectedText() is '#test-content 3 to 3'
+PASS rangeText(internals.rangeOfString('in-user-agent-shadow', range(userAgentShadowRoot, 0), ['DoNotTraverseFlatTree'])) is '(#user-agent-shadow-root, 0) 0 to 20'
+PASS rangeText(internals.rangeOfString('in-user-agent-shadow', range(userAgentShadowRoot, 0), [])) is '(#user-agent-shadow-root, 0) 0 to 20'
+PASS clearSelection(); internals.countFindMatches('in-document', ['DoNotTraverseFlatTree']) is 2
+PASS internals.countFindMatches('in-document', []) is 2
+PASS internals.countFindMatches('in-shadow', ['DoNotTraverseFlatTree']) is 0
+PASS internals.countFindMatches('in-shadow', []) is 2
+PASS internals.countFindMatches('in-', ['DoNotTraverseFlatTree']) is 2
+PASS internals.countFindMatches('in-', []) is 4
+PASS internals.countFindMatches('in-shadow in-document', ['DoNotTraverseFlatTree']) is 0
+PASS internals.countFindMatches('in-shadow in-document', []) is 0
+PASS successfullyParsed is true
+
+TEST COMPLETE
+in-document slotted in-document

Added: branches/safari-603-branch/LayoutTests/editing/text-iterator/find-string-on-flat-tree.html (0 => 210638)


--- branches/safari-603-branch/LayoutTests/editing/text-iterator/find-string-on-flat-tree.html	                        (rev 0)
+++ branches/safari-603-branch/LayoutTests/editing/text-iterator/find-string-on-flat-tree.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -0,0 +1,169 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="test-content">in-document <span id="host">unslotted <b id="slotted-element" slot="named-slot">slotted</b> unslotted</span> in-document<span id="user-agent-host"></span></div>
+<script src=""
+<script>
+
+description('This tests finding across shadow boundaries using the flat tree.');
+
+var testContent = document.getElementById('test-content');
+var shadowHost = document.getElementById('host');
+var shadowRoot = shadowHost.attachShadow({mode: 'closed'});
+shadowRoot.innerHTML = 'in-shadow <slot name="named-slot">in-slot</slot> in-shadow';
+shadowRoot.id = 'shadow-root';
+
+if (!window.internals)
+    testFailed('This test requires internals');
+else {
+    var userAgentShadowHost = document.getElementById('user-agent-host');
+    var userAgentShadowRoot = internals.ensureUserAgentShadowRoot(userAgentShadowHost);
+    userAgentShadowRoot.innerHTML = 'in-user-agent-shadow';
+    userAgentShadowRoot.id = 'user-agent-shadow-root';
+
+    // Hide console so that we don't end up finding text in the log itself.
+    document.getElementById('console').style.display = 'none';
+
+    function nodeLabel(node)
+    {
+        if (node.nodeType != Node.TEXT_NODE)
+            return '#' + node.id;
+        let offset = 0;
+        for (let child = node.previousSibling; child; child = child.previousSibling)
+            offset++;
+        return `(#${node.parentNode.id}, ${offset})`;
+    }
+
+    function rangeText(range)
+    {
+        if (!range)
+            return null;
+        if (range.startContainer == range.endContainer)
+            return `${nodeLabel(range.startContainer)} ${range.startOffset} to ${range.endOffset}`;
+        return `(${nodeLabel(range.startContainer)}, ${range.startOffset}) to (${nodeLabel(range.endContainer)}, ${range.endOffset})`;
+    }
+
+    function clearSelection()
+    {
+        getSelection().removeAllRanges();
+    }
+
+    function selectedText(range)
+    {
+        if (!getSelection().rangeCount)
+            return null;
+        return rangeText(getSelection().getRangeAt(0));
+    }
+
+    function setSelection(node, offset)
+    {
+        getSelection().setPosition(node, offset);
+    }
+
+    function range(node, offset)
+    {
+        let range = new Range;
+        range.setStart(node, offset);
+        return range;
+    }
+
+    shouldBe("clearSelection(); document.execCommand('FindString', null, 'in-document'); selectedText()", "'(#test-content, 0) 0 to 11'");
+    shouldBe("clearSelection(); window.find('in-document'); selectedText()", "'(#test-content, 0) 0 to 11'");
+    shouldBe("rangeText(internals.rangeOfString('in-document', null, ['DoNotTraverseFlatTree']))", "'(#test-content, 0) 0 to 11'");
+    shouldBe("rangeText(internals.rangeOfString('in-document', null, []))", "'(#test-content, 0) 0 to 11'");
+
+    shouldBe("clearSelection(); document.execCommand('FindString', null, 'in-shadow'); selectedText()", "null");
+    shouldBe("clearSelection(); window.find('in-shadow'); selectedText()", "null");
+    shouldBe("rangeText(internals.rangeOfString('in-shadow', null, ['DoNotTraverseFlatTree']))", "null");
+    shouldBe("rangeText(internals.rangeOfString('in-shadow', null, []))", "'(#shadow-root, 0) 0 to 9'");
+
+    shouldBe("clearSelection(); document.execCommand('FindString', null, 'unslotted'); selectedText()", "null");
+    shouldBe("clearSelection(); window.find('unslotted'); selectedText()", "null");
+    shouldBe("rangeText(internals.rangeOfString('unslotted', null, ['DoNotTraverseFlatTree']))", "null");
+    shouldBe("rangeText(internals.rangeOfString('unslotted', null, []))", "null");
+
+    shouldBe("clearSelection(); document.execCommand('FindString', null, 'slotted'); selectedText()", "'(#slotted-element, 0) 0 to 7'");
+    shouldBe("clearSelection(); window.find('slotted'); selectedText()", "'(#slotted-element, 0) 0 to 7'");
+    shouldBe("rangeText(internals.rangeOfString('slotted', null, ['DoNotTraverseFlatTree']))", "'(#slotted-element, 0) 0 to 7'");
+    shouldBe("rangeText(internals.rangeOfString('slotted', null, []))", "'(#slotted-element, 0) 0 to 7'");
+
+    shouldBe("clearSelection(); document.execCommand('FindString', null, 'slotted in-document'); selectedText()", "'((#slotted-element, 0), 0) to ((#test-content, 2), 12)'");
+    shouldBe("clearSelection(); window.find('slotted in-document'); selectedText()", "'((#slotted-element, 0), 0) to ((#test-content, 2), 12)'");
+    shouldBe("rangeText(internals.rangeOfString('slotted in-document', null, ['DoNotTraverseFlatTree']))", "'((#slotted-element, 0), 0) to ((#test-content, 2), 12)'");
+    shouldBe("rangeText(internals.rangeOfString('slotted in-document', null, []))", "null");
+
+    shouldBe("clearSelection(); document.execCommand('FindString', null, 'in-shadow in-document'); selectedText()", "null");
+    shouldBe("clearSelection(); window.find('in-shadow in-document'); selectedText()", "null");
+    shouldBe("rangeText(internals.rangeOfString('in-shadow in-document', null, ['DoNotTraverseFlatTree']))", "null");
+    shouldBe("rangeText(internals.rangeOfString('in-shadow in-document', null, []))", "null /* Can't return a range across shadow boundary */");
+
+    shouldBe("setSelection(testContent, 1); document.execCommand('FindString', null, 'in-document'); selectedText()", "'(#test-content, 2) 1 to 12'");
+    shouldBe("setSelection(testContent, 1); window.find('in-document'); selectedText()", "'(#test-content, 2) 1 to 12'");
+    shouldBe("rangeText(internals.rangeOfString('in-document', range(testContent, 1), ['DoNotTraverseFlatTree']))", "'(#test-content, 2) 1 to 12'");
+    shouldBe("rangeText(internals.rangeOfString('in-document', range(testContent, 1), []))", "'(#test-content, 2) 1 to 12'");
+
+    shouldBe("setSelection(shadowRoot, 0); document.execCommand('FindString', null, 'in-document'); selectedText()", "'(#test-content, 2) 1 to 12'");
+    shouldBe("setSelection(shadowRoot, 0); window.find('in-document'); selectedText()", "'(#test-content, 2) 1 to 12'");
+    shouldBe("rangeText(internals.rangeOfString('in-document', range(shadowRoot, 0), ['DoNotTraverseFlatTree']))", "'(#test-content, 2) 1 to 12'");
+    shouldBe("rangeText(internals.rangeOfString('in-document', range(shadowRoot, 0), []))", "'(#test-content, 2) 1 to 12'");
+
+    shouldBe("setSelection(shadowRoot, 0); document.execCommand('FindString', null, 'in-shadow'); selectedText()", "'#test-content 1 to 1'");
+    shouldBe("setSelection(shadowRoot, 0); window.find('in-shadow'); selectedText()", "'#test-content 1 to 1'");
+    shouldBe("rangeText(internals.rangeOfString('in-shadow', range(shadowRoot, 0), ['DoNotTraverseFlatTree']))", "'(#shadow-root, 0) 0 to 9'");
+    shouldBe("rangeText(internals.rangeOfString('in-shadow', range(shadowRoot, 0), []))", "'(#shadow-root, 0) 0 to 9'");
+
+    shouldBe("setSelection(shadowRoot, 0); document.execCommand('FindString', null, 'slotted'); selectedText()", "'(#slotted-element, 0) 0 to 7' /* Wrapped around */");
+    shouldBe("setSelection(shadowRoot, 0); window.find('slotted'); selectedText()", "'#test-content 1 to 1'");
+    shouldBe("setSelection(shadowRoot, 0); window.find('slotted', /* caseSensitive */ true, /* backwards */ false, /* wrap */ true); selectedText()", "'(#slotted-element, 0) 0 to 7'");
+    shouldBe("rangeText(internals.rangeOfString('slotted', range(shadowRoot, 0), ['DoNotTraverseFlatTree']))", "null");
+    shouldBe("rangeText(internals.rangeOfString('slotted', range(shadowRoot, 0), []))", "'(#slotted-element, 0) 0 to 7'");
+
+    shouldBe("setSelection(shadowRoot, 1); document.execCommand('FindString', null, 'slotted'); selectedText()", "'(#slotted-element, 0) 0 to 7' /* Wrapped around */");
+    shouldBe("setSelection(shadowRoot, 1); window.find('slotted'); selectedText()", "'#test-content 1 to 1'");
+    shouldBe("setSelection(shadowRoot, 1); window.find('slotted', /* caseSensitive */ true, /* backwards */ false, /* wrap */ true); selectedText()", "'(#slotted-element, 0) 0 to 7'");
+    shouldBe("rangeText(internals.rangeOfString('slotted', range(shadowRoot, 1), ['DoNotTraverseFlatTree']))", "null");
+    shouldBe("rangeText(internals.rangeOfString('slotted', range(shadowRoot, 1), []))", "'(#slotted-element, 0) 0 to 7'");
+
+    shouldBe("setSelection(shadowRoot, 1); document.execCommand('FindString', null, 'in-shadow'); selectedText()", "'#test-content 1 to 1'");
+    shouldBe("setSelection(shadowRoot, 1); window.find('in-shadow'); selectedText()", "'#test-content 1 to 1'");
+    shouldBe("rangeText(internals.rangeOfString('in-shadow', range(shadowRoot, 1), ['DoNotTraverseFlatTree']))", "'(#shadow-root, 2) 1 to 10'");
+    shouldBe("rangeText(internals.rangeOfString('in-shadow', range(shadowRoot, 1), []))", "'(#shadow-root, 2) 1 to 10'");
+
+    shouldBe("setSelection(shadowRoot, 1); document.execCommand('FindString', null, 'in-document'); selectedText()", "'(#test-content, 2) 1 to 12'");
+    shouldBe("setSelection(shadowRoot, 1); window.find('in-document'); selectedText()", "'(#test-content, 2) 1 to 12'");
+    shouldBe("rangeText(internals.rangeOfString('in-document', range(shadowRoot, 1), ['DoNotTraverseFlatTree']))", "'(#test-content, 2) 1 to 12'");
+    shouldBe("rangeText(internals.rangeOfString('in-document', range(shadowRoot, 1), []))", "'(#test-content, 2) 1 to 12'");
+
+    shouldBe("setSelection(shadowRoot, 1); document.execCommand('FindString', null, 'in-slot'); selectedText()", "'#test-content 1 to 1'");
+    shouldBe("setSelection(shadowRoot, 1); window.find('in-slot'); selectedText()", "'#test-content 1 to 1'");
+    shouldBe("rangeText(internals.rangeOfString('in-slot', range(shadowRoot, 1), ['DoNotTraverseFlatTree']))", "null");
+    shouldBe("rangeText(internals.rangeOfString('in-slot', range(shadowRoot, 1), []))", "null");
+
+    shouldBe("clearSelection(); document.execCommand('FindString', null, 'in-user-agent-shadow'); selectedText()", "null");
+    shouldBe("clearSelection(); window.find('in-user-agent-shadow'); selectedText()", "null");
+    shouldBe("rangeText(internals.rangeOfString('in-user-agent-shadow', null, ['DoNotTraverseFlatTree']))", "null");
+    shouldBe("rangeText(internals.rangeOfString('in-user-agent-shadow', null, []))", "null");
+
+    shouldBe("setSelection(userAgentShadowRoot, 0); document.execCommand('FindString', null, 'in-user-agent-shadow'); selectedText()", "'#test-content 3 to 3'");
+    shouldBe("setSelection(userAgentShadowRoot, 0); window.find('in-user-agent-shadow'); selectedText()", "'#test-content 3 to 3'");
+    shouldBe("rangeText(internals.rangeOfString('in-user-agent-shadow', range(userAgentShadowRoot, 0), ['DoNotTraverseFlatTree']))", "'(#user-agent-shadow-root, 0) 0 to 20'");
+    shouldBe("rangeText(internals.rangeOfString('in-user-agent-shadow', range(userAgentShadowRoot, 0), []))", "'(#user-agent-shadow-root, 0) 0 to 20'");
+
+    shouldBe("clearSelection(); internals.countFindMatches('in-document', ['DoNotTraverseFlatTree'])", "2");
+    shouldBe("internals.countFindMatches('in-document', [])", "2");
+
+    shouldBe("internals.countFindMatches('in-shadow', ['DoNotTraverseFlatTree'])", "0");
+    shouldBe("internals.countFindMatches('in-shadow', [])", "2");
+
+    shouldBe("internals.countFindMatches('in-', ['DoNotTraverseFlatTree'])", "2");
+    shouldBe("internals.countFindMatches('in-', [])", "4");
+
+    shouldBe("internals.countFindMatches('in-shadow in-document', ['DoNotTraverseFlatTree'])", "0");
+    shouldBe("internals.countFindMatches('in-shadow in-document', [])", "0");
+
+    document.getElementById('console').style.display = null;
+}
+
+</script>
+</body>
+</html>

Modified: branches/safari-603-branch/LayoutTests/fast/text/mark-matches-broken-line-rendering.html (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/fast/text/mark-matches-broken-line-rendering.html	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/fast/text/mark-matches-broken-line-rendering.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -11,6 +11,6 @@
 <script>
 if (window.internals) {
     internals.setMarkedTextMatchesAreHighlighted(true);
-    internals.countMatchesForText("Quo usque tandem abutere, Catilina, patientia nostra?", 0, "mark");
+    internals.countMatchesForText("Quo usque tandem abutere, Catilina, patientia nostra?", [], "mark");
 }
 </script>

Modified: branches/safari-603-branch/LayoutTests/fast/text/mark-matches-overflow-clip.html (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/fast/text/mark-matches-overflow-clip.html	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/fast/text/mark-matches-overflow-clip.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -17,7 +17,7 @@
     }
 
     testRunner.dumpAsText();
-    internals.countMatchesForText("tandem", 0, "mark");
+    internals.countMatchesForText("tandem", [], "mark");
     
     var markedNode = document.getElementsByTagName("span")[0].firstChild;
     document.write(internals.dumpMarkerRects("TextMatch"));

Modified: branches/safari-603-branch/LayoutTests/fast/text/mark-matches-rendering-simple-lines-expected.html (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/fast/text/mark-matches-rendering-simple-lines-expected.html	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/fast/text/mark-matches-rendering-simple-lines-expected.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -8,6 +8,6 @@
 <script>
 if (window.internals) {
     internals.setMarkedTextMatchesAreHighlighted(true);
-    internals.countMatchesForText("ti", 0, "mark");
+    internals.countMatchesForText("ti", [], "mark");
 }
 </script>

Modified: branches/safari-603-branch/LayoutTests/fast/text/mark-matches-rendering-simple-lines.html (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/fast/text/mark-matches-rendering-simple-lines.html	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/fast/text/mark-matches-rendering-simple-lines.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -4,6 +4,6 @@
 <script>
 if (window.internals) {
     internals.setMarkedTextMatchesAreHighlighted(true);
-    internals.countMatchesForText("ti", 0, "mark");
+    internals.countMatchesForText("ti", [], "mark");
 }
 </script>

Modified: branches/safari-603-branch/LayoutTests/fast/text/mark-matches-rendering.html (210637 => 210638)


--- branches/safari-603-branch/LayoutTests/fast/text/mark-matches-rendering.html	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/LayoutTests/fast/text/mark-matches-rendering.html	2017-01-12 16:44:58 UTC (rev 210638)
@@ -4,6 +4,6 @@
 <script>
 if (window.internals) {
     internals.setMarkedTextMatchesAreHighlighted(true);
-    internals.countMatchesForText("Quo usque tandem abutere, Catilina, patientia nostra?", 0, "mark");
+    internals.countMatchesForText("Quo usque tandem abutere, Catilina, patientia nostra?", [], "mark");
 }
 </script>

Modified: branches/safari-603-branch/Source/WebCore/ChangeLog (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/ChangeLog	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/ChangeLog	2017-01-12 16:44:58 UTC (rev 210638)
@@ -1,5 +1,60 @@
 2017-01-12  Matthew Hanson  <[email protected]>
 
+        Merge r210432. rdar://problem/29633667
+
+    2017-01-05  Ryosuke Niwa  <[email protected]>
+
+            Finding text doesn't work across shadow boundary
+            https://bugs.webkit.org/show_bug.cgi?id=158503
+
+            Reviewed by Antti Koivisto.
+
+            Added a new TextIterator behavior flag, TextIteratorTraversesFlatTree, which makes TextIterator traverse
+            the flat tree instead of the DOM tree, and made this behavior default in findPlainText.
+
+            Also added a new find options flag, DoNotTraverseFlatTree, to suppress this behavior in window.find(~)
+            and execCommand('FindString', false, ~) as they should not be able to peek information inside shadow trees.
+            Unfortunately these APIs have been deprecated in the standards so there is no specification to follow.
+
+            For now, we don't support finding a word or a keyword across a shadow boundary as this would require
+            making rangeOfString and other related functions return a Range-like object that can cross shadow boundaries.
+
+            Also added internals.rangeOfString to test Editor::rangeOfString, and replaced the bit-flag arguments
+            to internals.countMatchesForText and internals.countFindMatches by an array of strings for better portability.
+
+            Test: editing/text-iterator/find-string-on-flat-tree.html
+
+            * editing/Editor.cpp:
+            (WebCore::Editor::rangeOfString): Use the modern containingShadowRoot instead of nonBoundaryShadowTreeRootNode
+            since the start container can be a shadow root, which nonBoundaryShadowTreeRootNode asserts not be the case.
+            * editing/Editor.h:
+            * editing/EditorCommand.cpp:
+            (WebCore::executeFindString): Don't traverse across shadow boundaries.
+            * editing/FindOptions.h: Added DoNotTraverseFlatTree.
+            * editing/TextIterator.cpp:
+            (WebCore::assignedAuthorSlot): Added.
+            (WebCore::authorShadowRoot): Added.
+            (WebCore::firstChildInFlatTreeIgnoringUserAgentShadow): Added.
+            (WebCore::nextSiblingInFlatTreeIgnoringUserAgentShadow): Added.
+            (WebCore::firstChild): Added. Traverses the flat tree when TextIteratorTraversesFlatTree is set.
+            (WebCore::nextSibling): Ditto.
+            (WebCore::parentNodeOrShadowHost): Ditto.
+            (WebCore::TextIterator::advance): Don't set m_handledChildren to true when the current node has display: contents.
+            (WebCore::findPlainText): Use TextIteratorTraversesFlatTree unless DoNotTraverseFlatTree is set.
+            * editing/TextIteratorBehavior.h: Added TextIteratorTraversesFlatTree.
+            * page/DOMWindow.cpp:
+            (WebCore::DOMWindow::find): Don't traverse across shadow boundaries.
+            * testing/Internals.cpp:
+            (WebCore::parseFindOptions): Added.
+            (WebCore::Internals::rangeOfString): Added.
+            (WebCore::Internals::countMatchesForText): Replaced the find options by an array of strings instead of a bit mask.
+            (WebCore::Internals::countFindMatches): Ditto.
+            * testing/Internals.h:
+            * testing/Internals.idl: Added rangeOfString, and replaced find options bit-flag in countMatchesForText and
+            countFindMatches by an array of strings so that the tests themselves don't rely on a specific value of each bit flag.
+
+2017-01-12  Matthew Hanson  <[email protected]>
+
         Merge r210131. rdar://problem/29633667
 
     2016-12-23  Ryosuke Niwa  <[email protected]>

Modified: branches/safari-603-branch/Source/WebCore/editing/Editor.cpp (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/editing/Editor.cpp	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/editing/Editor.cpp	2017-01-12 16:44:58 UTC (rev 210638)
@@ -3132,7 +3132,7 @@
             searchRange->setEnd(startInReferenceRange ? referenceRange->endPosition() : referenceRange->startPosition());
     }
 
-    RefPtr<Node> shadowTreeRoot = referenceRange ? referenceRange->startContainer().nonBoundaryShadowTreeRootNode() : nullptr;
+    RefPtr<ShadowRoot> shadowTreeRoot = referenceRange ? referenceRange->startContainer().containingShadowRoot() : nullptr;
     if (shadowTreeRoot) {
         if (forward)
             searchRange->setEnd(*shadowTreeRoot, shadowTreeRoot->countChildNodes());

Modified: branches/safari-603-branch/Source/WebCore/editing/Editor.h (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/editing/Editor.h	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/editing/Editor.h	2017-01-12 16:44:58 UTC (rev 210638)
@@ -378,7 +378,7 @@
     String selectedTextForDataTransfer() const;
     WEBCORE_EXPORT bool findString(const String&, FindOptions);
 
-    RefPtr<Range> rangeOfString(const String&, Range*, FindOptions);
+    WEBCORE_EXPORT RefPtr<Range> rangeOfString(const String&, Range*, FindOptions);
 
     const VisibleSelection& mark() const; // Mark, to be used as emacs uses it.
     void setMark(const VisibleSelection&);

Modified: branches/safari-603-branch/Source/WebCore/editing/EditorCommand.cpp (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/editing/EditorCommand.cpp	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/editing/EditorCommand.cpp	2017-01-12 16:44:58 UTC (rev 210638)
@@ -377,7 +377,7 @@
 
 static bool executeFindString(Frame& frame, Event*, EditorCommandSource, const String& value)
 {
-    return frame.editor().findString(value, CaseInsensitive | WrapAround);
+    return frame.editor().findString(value, CaseInsensitive | WrapAround | DoNotTraverseFlatTree);
 }
 
 static bool executeFontName(Frame& frame, Event*, EditorCommandSource source, const String& value)

Modified: branches/safari-603-branch/Source/WebCore/editing/FindOptions.h (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/editing/FindOptions.h	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/editing/FindOptions.h	2017-01-12 16:44:58 UTC (rev 210638)
@@ -37,9 +37,10 @@
     WrapAround = 1 << 4,
     StartInSelection = 1 << 5,
     DoNotRevealSelection = 1 << 6,
-    AtWordEnds = 1 << 7
+    AtWordEnds = 1 << 7,
+    DoNotTraverseFlatTree = 1 << 8,
 };
 
-typedef unsigned char FindOptions;
+typedef unsigned short FindOptions;
 
 } // namespace WebCore

Modified: branches/safari-603-branch/Source/WebCore/editing/TextIterator.cpp (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/editing/TextIterator.cpp	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/editing/TextIterator.cpp	2017-01-12 16:44:58 UTC (rev 210638)
@@ -381,6 +381,69 @@
 {
 }
 
+static HTMLSlotElement* assignedAuthorSlot(Node& node)
+{
+    auto* slot = node.assignedSlot();
+    if (!slot || slot->containingShadowRoot()->mode() == ShadowRootMode::UserAgent)
+        return nullptr;
+    return slot;
+}
+
+static ShadowRoot* authorShadowRoot(Node& node)
+{
+    auto* shadowRoot = node.shadowRoot();
+    if (!shadowRoot || shadowRoot->mode() == ShadowRootMode::UserAgent)
+        return nullptr;
+    return shadowRoot;
+}
+
+// FIXME: Use ComposedTreeIterator instead. These functions are more expensive because they might do O(n) work.
+static inline Node* firstChildInFlatTreeIgnoringUserAgentShadow(Node& node)
+{
+    if (auto* shadowRoot = authorShadowRoot(node))
+        return shadowRoot->firstChild();
+    if (is<HTMLSlotElement>(node)) {
+        if (auto* assignedNodes = downcast<HTMLSlotElement>(node).assignedNodes())
+            return assignedNodes->at(0);
+    }
+    return node.firstChild();
+}
+
+static inline Node* nextSiblingInFlatTreeIgnoringUserAgentShadow(Node& node)
+{
+    if (auto* slot = assignedAuthorSlot(node)) {
+        auto* assignedNodes = slot->assignedNodes();
+        ASSERT(assignedNodes);
+        auto nodeIndex = assignedNodes->find(&node);
+        ASSERT(nodeIndex != notFound);
+        if (assignedNodes->size() > nodeIndex + 1)
+            return assignedNodes->at(nodeIndex + 1);
+        return nullptr;
+    }
+    return node.nextSibling();
+}
+
+static inline Node* firstChild(TextIteratorBehavior options, Node& node)
+{
+    if (UNLIKELY(options & TextIteratorTraversesFlatTree))
+        return firstChildInFlatTreeIgnoringUserAgentShadow(node);
+    return node.firstChild();
+}
+
+static inline Node* nextSibling(TextIteratorBehavior options, Node& node)
+{
+    if (UNLIKELY(options & TextIteratorTraversesFlatTree))
+        return nextSiblingInFlatTreeIgnoringUserAgentShadow(node);
+    return node.nextSibling();
+}
+
+static inline Node* parentNodeOrShadowHost(TextIteratorBehavior options, Node& node)
+{
+    if (UNLIKELY(options & TextIteratorTraversesFlatTree))
+        return node.parentInComposedTree();
+    return node.parentOrShadowHostNode();
+}
+
 void TextIterator::advance()
 {
     ASSERT(!atEnd());
@@ -430,7 +493,7 @@
         auto* renderer = m_node->renderer();
         if (!renderer) {
             m_handledNode = true;
-            m_handledChildren = true;
+            m_handledChildren = !((m_behavior & TextIteratorTraversesFlatTree) && is<Element>(*m_node) && downcast<Element>(*m_node).hasDisplayContents());
         } else {
             // handle current node according to its type
             if (!m_handledNode) {
@@ -447,13 +510,13 @@
 
         // find a new current node to handle in depth-first manner,
         // calling exitNode() as we come back thru a parent node
-        Node* next = m_handledChildren ? nullptr : m_node->firstChild();
+        Node* next = m_handledChildren ? nullptr : firstChild(m_behavior, *m_node);
         m_offset = 0;
         if (!next) {
-            next = m_node->nextSibling();
+            next = nextSibling(m_behavior, *m_node);
             if (!next) {
                 bool pastEnd = NodeTraversal::next(*m_node) == m_pastEndNode;
-                Node* parentNode = m_node->parentOrShadowHostNode();
+                Node* parentNode = parentNodeOrShadowHost(m_behavior, *m_node);
                 while (!next && parentNode) {
                     if ((pastEnd && parentNode == m_endContainer) || m_endContainer->isDescendantOf(*parentNode))
                         return;
@@ -461,7 +524,7 @@
                     Node* exitedNode = m_node;
                     m_node = parentNode;
                     m_fullyClippedStack.pop();
-                    parentNode = m_node->parentOrShadowHostNode();
+                    parentNode = parentNodeOrShadowHost(m_behavior, *m_node);
                     if (haveRenderer)
                         exitNode(exitedNode);
                     if (m_positionNode) {
@@ -469,7 +532,7 @@
                         m_handledChildren = true;
                         return;
                     }
-                    next = m_node->nextSibling();
+                    next = nextSibling(m_behavior, *m_node);
                 }
             }
             m_fullyClippedStack.pop();            
@@ -2640,6 +2703,8 @@
 
     bool searchForward = !(options & Backwards);
     TextIteratorBehavior iteratorOptions = TextIteratorEntersTextControls | TextIteratorClipsToFrameAncestors;
+    if (!(options & DoNotTraverseFlatTree))
+        iteratorOptions |= TextIteratorTraversesFlatTree;
 
     CharacterIterator findIterator(range, iteratorOptions);
     auto result = findPlainTextOffset(buffer, findIterator, searchForward);

Modified: branches/safari-603-branch/Source/WebCore/editing/TextIteratorBehavior.h (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/editing/TextIteratorBehavior.h	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/editing/TextIteratorBehavior.h	2017-01-12 16:44:58 UTC (rev 210638)
@@ -57,6 +57,8 @@
     // Makes visiblity test take into account the visibility of the frame.
     // FIXME: This should probably be always on unless TextIteratorIgnoresStyleVisibility is set.
     TextIteratorClipsToFrameAncestors = 1 << 8,
+
+    TextIteratorTraversesFlatTree = 1 << 9,
 };
 
 typedef unsigned short TextIteratorBehavior;

Modified: branches/safari-603-branch/Source/WebCore/page/DOMWindow.cpp (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/page/DOMWindow.cpp	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/page/DOMWindow.cpp	2017-01-12 16:44:58 UTC (rev 210638)
@@ -1207,7 +1207,7 @@
 
     // FIXME (13016): Support wholeWord, searchInFrames and showDialog.    
     FindOptions options = (backwards ? Backwards : 0) | (caseSensitive ? 0 : CaseInsensitive) | (wrap ? WrapAround : 0);
-    return m_frame->editor().findString(string, options);
+    return m_frame->editor().findString(string, options | DoNotTraverseFlatTree);
 }
 
 bool DOMWindow::offscreenBuffering() const

Modified: branches/safari-603-branch/Source/WebCore/testing/Internals.cpp (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/testing/Internals.cpp	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/testing/Internals.cpp	2017-01-12 16:44:58 UTC (rev 210638)
@@ -1822,23 +1822,76 @@
     document->frame()->editor().toggleOverwriteModeEnabled();
 }
 
-unsigned Internals::countMatchesForText(const String& text, unsigned findOptions, const String& markMatches)
+static ExceptionOr<FindOptions> parseFindOptions(const Vector<String>& optionList)
 {
+    const struct {
+        const char* name;
+        FindOptionFlag value;
+    } flagList[] = {
+        {"CaseInsensitive", CaseInsensitive},
+        {"AtWordStarts", AtWordStarts},
+        {"TreatMedialCapitalAsWordStart", TreatMedialCapitalAsWordStart},
+        {"Backwards", Backwards},
+        {"WrapAround", WrapAround},
+        {"StartInSelection", StartInSelection},
+        {"DoNotRevealSelection", DoNotRevealSelection},
+        {"AtWordEnds", AtWordEnds},
+        {"DoNotTraverseFlatTree", DoNotTraverseFlatTree},
+    };
+    FindOptions result = 0;
+    for (auto& option : optionList) {
+        bool found = false;
+        for (auto& flag : flagList) {
+            if (flag.name == option) {
+                result |= flag.value;
+                found = true;
+                break;
+            }
+        }
+        if (!found)
+            return Exception { SYNTAX_ERR };
+    }
+    return result;
+}
+
+ExceptionOr<RefPtr<Range>> Internals::rangeOfString(const String& text, RefPtr<Range>&& referenceRange, const Vector<String>& findOptions)
+{
     Document* document = contextDocument();
     if (!document || !document->frame())
-        return 0;
+        return Exception { INVALID_ACCESS_ERR };
 
+    auto parsedOptions = parseFindOptions(findOptions);
+    if (parsedOptions.hasException())
+        return parsedOptions.releaseException();
+
+    return document->frame()->editor().rangeOfString(text, referenceRange.get(), parsedOptions.releaseReturnValue());
+}
+
+ExceptionOr<unsigned> Internals::countMatchesForText(const String& text, const Vector<String>& findOptions, const String& markMatches)
+{
+    Document* document = contextDocument();
+    if (!document || !document->frame())
+        return Exception { INVALID_ACCESS_ERR };
+
+    auto parsedOptions = parseFindOptions(findOptions);
+    if (parsedOptions.hasException())
+        return parsedOptions.releaseException();
+
     bool mark = markMatches == "mark";
-    return document->frame()->editor().countMatchesForText(text, nullptr, findOptions, 1000, mark, nullptr);
+    return document->frame()->editor().countMatchesForText(text, nullptr, parsedOptions.releaseReturnValue(), 1000, mark, nullptr);
 }
 
-unsigned Internals::countFindMatches(const String& text, unsigned findOptions)
+ExceptionOr<unsigned> Internals::countFindMatches(const String& text, const Vector<String>& findOptions)
 {
     Document* document = contextDocument();
     if (!document || !document->page())
-        return 0;
+        return Exception { INVALID_ACCESS_ERR };
 
-    return document->page()->countFindMatches(text, findOptions, 1000);
+    auto parsedOptions = parseFindOptions(findOptions);
+    if (parsedOptions.hasException())
+        return parsedOptions.releaseException();
+
+    return document->page()->countFindMatches(text, parsedOptions.releaseReturnValue(), 1000);
 }
 
 unsigned Internals::numberOfLiveNodes() const

Modified: branches/safari-603-branch/Source/WebCore/testing/Internals.h (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/testing/Internals.h	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/testing/Internals.h	2017-01-12 16:44:58 UTC (rev 210638)
@@ -237,8 +237,9 @@
     bool isOverwriteModeEnabled();
     void toggleOverwriteModeEnabled();
 
-    unsigned countMatchesForText(const String&, unsigned findOptions, const String& markMatches);
-    unsigned countFindMatches(const String&, unsigned findOptions);
+    ExceptionOr<RefPtr<Range>> rangeOfString(const String&, RefPtr<Range>&&, const Vector<String>& findOptions);
+    ExceptionOr<unsigned> countMatchesForText(const String&, const Vector<String>& findOptions, const String& markMatches);
+    ExceptionOr<unsigned> countFindMatches(const String&, const Vector<String>& findOptions);
 
     unsigned numberOfScrollableAreas();
 

Modified: branches/safari-603-branch/Source/WebCore/testing/Internals.idl (210637 => 210638)


--- branches/safari-603-branch/Source/WebCore/testing/Internals.idl	2017-01-12 16:44:49 UTC (rev 210637)
+++ branches/safari-603-branch/Source/WebCore/testing/Internals.idl	2017-01-12 16:44:58 UTC (rev 210638)
@@ -178,9 +178,11 @@
     void setEditingValue(HTMLInputElement inputElement, DOMString value);
     void setAutofilled(HTMLInputElement inputElement, boolean enabled);
     void setShowAutoFillButton(HTMLInputElement inputElement, AutoFillButtonType autoFillButtonType);
-    unsigned long countMatchesForText(DOMString text, unsigned long findOptions, DOMString markMatches);
-    unsigned long countFindMatches(DOMString text, unsigned long findOptions);
 
+    [MayThrowException] Range? rangeOfString(DOMString text, Range? referenceRange, sequence<DOMString> findOptions);
+    [MayThrowException] unsigned long countMatchesForText(DOMString text, sequence<DOMString> findOptions, DOMString markMatches);
+    [MayThrowException] unsigned long countFindMatches(DOMString text, sequence<DOMString> findOptions);
+
     [MayThrowException] DOMString autofillFieldName(Element formControlElement);
 
     [MayThrowException] void paintControlTints();
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to