<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[171676] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/171676">171676</a></dd>
<dt>Author</dt> <dd>abucur@adobe.com</dd>
<dt>Date</dt> <dd>2014-07-28 06:19:22 -0700 (Mon, 28 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>REGRESSION (<a href="http://trac.webkit.org/projects/webkit/changeset/169105">r169105</a>): Crash in selection
https://bugs.webkit.org/show_bug.cgi?id=134303

Patch by Radu Stavila &lt;stavila@adobe.com&gt; on 2014-07-28
Reviewed by Mihnea Ovidenie.

Source/WebCore:

When splitting the selection between different subtrees, all subtrees must have their selection cleared before
starting to apply the new selection. Otherwise, when selecting objects in a named flow thread and going up
its containing block chain, we can end up in the view's selection root, which has not yet been updated and so
we get inconsistent data.

To achieve this goal, the selection update was split into a &quot;clear&quot; and an &quot;apply&quot; method. The updateSelectionForSubtrees
method first iterates through all subtrees and performs the &quot;clear&quot; method and then starts all over again
and performs the &quot;apply&quot; method.

Test: fast/regions/selection/crash-deselect.html

* WebCore.xcodeproj/project.pbxproj:
* rendering/RenderSelectionInfo.h:
* rendering/RenderView.cpp:
(WebCore::RenderView::setSelection):
(WebCore::RenderView::splitSelectionBetweenSubtrees):
(WebCore::RenderView::updateSelectionForSubtrees): Added, clears and re-applies selection for all selection subtrees.
(WebCore::RenderView::clearSubtreeSelection): Added, clears selection and returns previously selected information.
(WebCore::RenderView::applySubtreeSelection): Added, updates the selection status of all objects inside the selection tree, compares old and new data and repaints accordingly.
(WebCore::RenderView::setSubtreeSelection): Deleted.
* rendering/RenderView.h:
* rendering/SelectionSubtreeRoot.cpp:
(WebCore::SelectionSubtreeRoot::SelectionSubtreeRoot):
* rendering/SelectionSubtreeRoot.h:
(WebCore::SelectionSubtreeRoot::OldSelectionData::OldSelectionData):

LayoutTests:

Added test for the crash that occurred in some cases when selecting.

Reviewed by NOBODY (OOPS!).

* fast/regions/selection/crash-deselect-expected.txt: Added.
* fast/regions/selection/crash-deselect.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCorexcodeprojprojectpbxproj">trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderSelectionInfoh">trunk/Source/WebCore/rendering/RenderSelectionInfo.h</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderViewcpp">trunk/Source/WebCore/rendering/RenderView.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderViewh">trunk/Source/WebCore/rendering/RenderView.h</a></li>
<li><a href="#trunkSourceWebCorerenderingSelectionSubtreeRootcpp">trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingSelectionSubtreeRooth">trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastregionsselectioncrashdeselectexpectedtxt">trunk/LayoutTests/fast/regions/selection/crash-deselect-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastregionsselectioncrashdeselecthtml">trunk/LayoutTests/fast/regions/selection/crash-deselect.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (171675 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-07-28 09:48:44 UTC (rev 171675)
+++ trunk/LayoutTests/ChangeLog        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2014-07-28  Radu Stavila  &lt;stavila@adobe.com&gt;
+
+        REGRESSION (r169105): Crash in selection
+        https://bugs.webkit.org/show_bug.cgi?id=134303
+
+        Added test for the crash that occurred in some cases when selecting.
+
+        Reviewed by Mihnea Ovidenie.
+
+        * fast/regions/selection/crash-deselect-expected.txt: Added.
+        * fast/regions/selection/crash-deselect.html: Added.
+
</ins><span class="cx"> 2014-07-28  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         CSS: Fix :visited behavior for SubSelectors
</span></span></pre></div>
<a id="trunkLayoutTestsfastregionsselectioncrashdeselectexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/regions/selection/crash-deselect-expected.txt (0 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/regions/selection/crash-deselect-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/regions/selection/crash-deselect-expected.txt        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+CONSOLE MESSAGE: line 66: HierarchyRequestError: DOM Exception 3: A Node was inserted somewhere it doesn't belong.
+
+Errlog selectionTest: HierarchyRequestError: HierarchyRequestError: DOM Exception 3 : index 1 
+Errlog webtest_fn_24: 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastregionsselectioncrashdeselecthtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/regions/selection/crash-deselect.html (0 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/regions/selection/crash-deselect.html                                (rev 0)
+++ trunk/LayoutTests/fast/regions/selection/crash-deselect.html        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -0,0 +1,72 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html id=&quot;webtest0&quot;&gt;
+    &lt;head id=&quot;webtest1&quot;&gt;
+        &lt;style id=&quot;webtest2&quot;&gt;&lt;/style&gt;
+        &lt;style&gt;
+            :last-child { -webkit-flow-into: foo; }
+        &lt;/style&gt;
+        
+    &lt;/head&gt;
+    &lt;body id=&quot;webtest3&quot;&gt;
+        &lt;script id=&quot;example&quot;&gt;&lt;/script&gt;
+
+        &lt;script type=&quot;text/javascript&quot;&gt;
+            if (window.testRunner)
+                testRunner.dumpAsText(false);
+        &lt;/script&gt;
+
+        &lt;script&gt;
+            var new_elem = document.createElement(&quot;canvas&quot;);
+            new_elem.setAttribute(&quot;id&quot;, &quot;webtest11&quot;);
+            document.querySelector(&quot;#webtest0&quot;).appendChild(new_elem);
+
+            document.write(&quot;&lt;br&gt;&lt;summary&gt;&quot;);
+        &lt;/script&gt;
+        &lt;summary&gt;
+            &lt;mathml id=&quot;webtest12&quot;&gt;
+                &lt;femerge&gt;&lt;/femerge&gt;
+            &lt;/mathml&gt;
+
+            &lt;script&gt;
+                function selectionTest() {
+                    try {
+                        wf_i = 0;
+                        for (; wf_i&lt;40; wf_i++) {
+                            var range = document.createRange();
+
+                            range.setStartBefore(document.getElementById(&quot;webtest3&quot;));
+                            range.setEndAfter(document.getElementById(&quot;webtest2&quot;));
+                            range.deleteContents();
+                            
+                            var markElement = document.getElementById(&quot;webtest1&quot;).appendChild(document.createElementNS(&quot;&quot;, &quot;mark&quot;));
+                            range.setStartAfter(markElement);
+
+                            var appletElement = document.getElementById(&quot;example&quot;).appendChild(document.createElement(&quot;applet&quot;));
+                            range.setEndAfter(appletElement);
+
+                            range.insertNode(document.getElementById(&quot;example&quot;));
+                        }
+                    } catch(e) {
+                      document.write(&quot;Errlog selectionTest: &quot; + e.name + &quot;: &quot; + e.message + &quot; : index &quot; + wf_i + &quot; &lt;br&gt;&lt;table/&gt;&quot;);
+                    }
+                }
+                selectionTest();
+            &lt;/script&gt;
+            &lt;sub&gt;
+
+            &lt;script&gt;
+                document.designMode = &quot;on&quot;;
+                document.execCommand(&quot;SelectAll&quot;);
+                document.write(&quot;Errlog webtest_fn_24: &lt;br&gt;&lt;nobr&gt;&quot;);
+
+                var femergeElement = document.getElementById(&quot;webtest12&quot;).appendChild(document.createElement(&quot;femerge&quot;));
+                var appletElement = document.getElementById(&quot;example&quot;).appendChild(document.createElement(&quot;applet&quot;));
+                var gradientElement = document.body.appendChild(document.createElement(&quot;gradient&quot;));
+                        
+                document.getElementById(&quot;webtest2&quot;).isEqualNode(femergeElement.insertBefore(document.documentElement, gradientElement));
+            &lt;/script&gt;
+
+            &lt;table&gt;&lt;/table&gt;
+        &lt;/summary&gt;
+    &lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (171675 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-07-28 09:48:44 UTC (rev 171675)
+++ trunk/Source/WebCore/ChangeLog        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2014-07-28  Radu Stavila  &lt;stavila@adobe.com&gt;
+
+        REGRESSION (r169105): Crash in selection
+        https://bugs.webkit.org/show_bug.cgi?id=134303
+
+        Reviewed by Mihnea Ovidenie.
+
+        When splitting the selection between different subtrees, all subtrees must have their selection cleared before
+        starting to apply the new selection. Otherwise, when selecting objects in a named flow thread and going up
+        its containing block chain, we can end up in the view's selection root, which has not yet been updated and so
+        we get inconsistent data.
+
+        To achieve this goal, the selection update was split into a &quot;clear&quot; and an &quot;apply&quot; method. The updateSelectionForSubtrees
+        method first iterates through all subtrees and performs the &quot;clear&quot; method and then starts all over again
+        and performs the &quot;apply&quot; method.
+
+        Test: fast/regions/selection/crash-deselect.html
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/RenderSelectionInfo.h:
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::setSelection):
+        (WebCore::RenderView::splitSelectionBetweenSubtrees):
+        (WebCore::RenderView::updateSelectionForSubtrees): Added, clears and re-applies selection for all selection subtrees.
+        (WebCore::RenderView::clearSubtreeSelection): Added, clears selection and returns previously selected information.
+        (WebCore::RenderView::applySubtreeSelection): Added, updates the selection status of all objects inside the selection tree, compares old and new data and repaints accordingly.
+        (WebCore::RenderView::setSubtreeSelection): Deleted.
+        * rendering/RenderView.h:
+        * rendering/SelectionSubtreeRoot.cpp:
+        (WebCore::SelectionSubtreeRoot::SelectionSubtreeRoot):
+        * rendering/SelectionSubtreeRoot.h:
+        (WebCore::SelectionSubtreeRoot::OldSelectionData::OldSelectionData):
+
</ins><span class="cx"> 2014-07-28  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         CSS: Fix :visited behavior for SubSelectors
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (171675 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-07-28 09:48:44 UTC (rev 171675)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -466,7 +466,7 @@
</span><span class="cx">                 0F09087F1444FDB200028917 /* ScrollbarTheme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE71415142189FC00DB33BA /* ScrollbarTheme.cpp */; };
</span><span class="cx">                 0F099D0817B968A100FF84B9 /* WebCoreTypedArrayController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F099D0617B968A100FF84B9 /* WebCoreTypedArrayController.cpp */; };
</span><span class="cx">                 0F099D0917B968A100FF84B9 /* WebCoreTypedArrayController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F099D0717B968A100FF84B9 /* WebCoreTypedArrayController.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><del>-                0F11A54F0F39233100C37884 /* RenderSelectionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F11A54E0F39233100C37884 /* RenderSelectionInfo.h */; };
</del><ins>+                0F11A54F0F39233100C37884 /* RenderSelectionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F11A54E0F39233100C37884 /* RenderSelectionInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F13163E16ED0CC80035CC04 /* PlatformCAFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13163D16ED0CC80035CC04 /* PlatformCAFilters.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F13164016ED0CDE0035CC04 /* PlatformCAFiltersMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F13163F16ED0CDE0035CC04 /* PlatformCAFiltersMac.mm */; };
</span><span class="cx">                 0F15DA8A0F3AAEE70000CE47 /* AnimationControllerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15DA890F3AAEE70000CE47 /* AnimationControllerPrivate.h */; };
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderSelectionInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderSelectionInfo.h (171675 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderSelectionInfo.h        2014-07-28 09:48:44 UTC (rev 171675)
+++ trunk/Source/WebCore/rendering/RenderSelectionInfo.h        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -25,8 +25,9 @@
</span><span class="cx"> #ifndef RenderSelectionInfo_h
</span><span class="cx"> #define RenderSelectionInfo_h
</span><span class="cx"> 
</span><ins>+#include &quot;GapRects.h&quot;
</ins><span class="cx"> #include &quot;IntRect.h&quot;
</span><del>-#include &quot;RenderBox.h&quot;
</del><ins>+#include &quot;RenderBlock.h&quot;
</ins><span class="cx"> #include &quot;RenderText.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderViewcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderView.cpp (171675 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderView.cpp        2014-07-28 09:48:44 UTC (rev 171675)
+++ trunk/Source/WebCore/rendering/RenderView.cpp        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -857,7 +857,9 @@
</span><span class="cx"> 
</span><span class="cx">     // If there is no RenderNamedFlowThreads we follow the regular selection.
</span><span class="cx">     if (!hasRenderNamedFlowThreads()) {
</span><del>-        setSubtreeSelection(*this, start, startPos, end, endPos, blockRepaintMode);
</del><ins>+        RenderSubtreesMap singleSubtreeMap;
+        singleSubtreeMap.set(this, SelectionSubtreeRoot(start, startPos, end, endPos));
+        updateSelectionForSubtrees(singleSubtreeMap, blockRepaintMode);
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -867,7 +869,6 @@
</span><span class="cx"> void RenderView::splitSelectionBetweenSubtrees(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
</span><span class="cx"> {
</span><span class="cx">     // Compute the visible selection end points for each of the subtrees.
</span><del>-    typedef HashMap&lt;SelectionSubtreeRoot*, SelectionSubtreeRoot&gt; RenderSubtreesMap;
</del><span class="cx">     RenderSubtreesMap renderSubtreesMap;
</span><span class="cx"> 
</span><span class="cx">     SelectionSubtreeRoot initialSelection;
</span><span class="lines">@@ -901,33 +902,50 @@
</span><span class="cx">             renderSubtreesMap.set(&amp;root, selectionData);
</span><span class="cx">         }
</span><span class="cx">     }
</span><ins>+    
+    updateSelectionForSubtrees(renderSubtreesMap, blockRepaintMode);
+}
</ins><span class="cx"> 
</span><del>-    for (RenderSubtreesMap::iterator i = renderSubtreesMap.begin(); i != renderSubtreesMap.end(); ++i) {
-        SelectionSubtreeRoot subtreeSelectionData = i-&gt;value;
-        subtreeSelectionData.adjustForVisibleSelection(document());
-        setSubtreeSelection(*i-&gt;key, subtreeSelectionData.selectionStart(), subtreeSelectionData.selectionStartPos(),
-            subtreeSelectionData.selectionEnd(), subtreeSelectionData.selectionEndPos(), blockRepaintMode);
</del><ins>+void RenderView::updateSelectionForSubtrees(RenderSubtreesMap&amp; renderSubtreesMap, SelectionRepaintMode blockRepaintMode)
+{
+    SubtreeOldSelectionDataMap oldSelectionDataMap;
+    for (auto it = renderSubtreesMap.begin(); it != renderSubtreesMap.end(); ++it) {
+        SelectionSubtreeRoot&amp; subtreeSelectionData = it-&gt;value;
+        if (hasRenderNamedFlowThreads())
+            subtreeSelectionData.adjustForVisibleSelection(document());
+
+        std::unique_ptr&lt;OldSelectionData&gt; oldSelectionData = std::make_unique&lt;OldSelectionData&gt;();
+        clearSubtreeSelection(*it-&gt;key, blockRepaintMode, *oldSelectionData);
+        oldSelectionDataMap.set(it-&gt;key, WTF::move(oldSelectionData));
+
+        SelectionSubtreeRoot&amp; root = *it-&gt;key;
+        root.setSelectionStart(subtreeSelectionData.selectionStart());
+        root.setSelectionStartPos(subtreeSelectionData.selectionStartPos());
+        root.setSelectionEnd(subtreeSelectionData.selectionEnd());
+        root.setSelectionEndPos(subtreeSelectionData.selectionEndPos());
</ins><span class="cx">     }
</span><ins>+
+    // Update selection status for the objects inside the selection subtrees.
+    // This needs to be done after the previous loop updated the selectionStart/End
+    // parameters of all subtrees because we're going to be climbing up the containing
+    // block chain and we might end up in a different selection subtree.
+    for (auto it = renderSubtreesMap.begin(); it != renderSubtreesMap.end(); ++it) {
+        SelectionSubtreeRoot subtreeSelectionData = it-&gt;value;
+        OldSelectionData&amp; oldSelectionData = *oldSelectionDataMap.get(it-&gt;key);
+        applySubtreeSelection(*it-&gt;key, subtreeSelectionData.selectionStart(), subtreeSelectionData.selectionEnd(), subtreeSelectionData.selectionEndPos(), blockRepaintMode, oldSelectionData);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void RenderView::setSubtreeSelection(SelectionSubtreeRoot&amp; root, RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
</del><ins>+void RenderView::clearSubtreeSelection(const SelectionSubtreeRoot&amp; root, SelectionRepaintMode blockRepaintMode, OldSelectionData&amp; oldSelectionData)
</ins><span class="cx"> {
</span><span class="cx">     // Record the old selected objects.  These will be used later
</span><span class="cx">     // when we compare against the new selected objects.
</span><del>-    int oldStartPos = root.selectionStartPos();
-    int oldEndPos = root.selectionEndPos();
-
-    // Objects each have a single selection rect to examine.
-    typedef HashMap&lt;RenderObject*, std::unique_ptr&lt;RenderSelectionInfo&gt;&gt; SelectedObjectMap;
-    SelectedObjectMap oldSelectedObjects;
-    SelectedObjectMap newSelectedObjects;
-
</del><ins>+    oldSelectionData.selectionStartPos = root.selectionStartPos();
+    oldSelectionData.selectionEndPos = root.selectionEndPos();
+    
</ins><span class="cx">     // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
</span><span class="cx">     // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
</span><span class="cx">     // the union of those rects might remain the same even when changes have occurred.
</span><del>-    typedef HashMap&lt;RenderBlock*, std::unique_ptr&lt;RenderBlockSelectionInfo&gt;&gt; SelectedBlockMap;
-    SelectedBlockMap oldSelectedBlocks;
-    SelectedBlockMap newSelectedBlocks;
</del><span class="cx"> 
</span><span class="cx">     RenderObject* os = root.selectionStart();
</span><span class="cx">     RenderObject* stop = rendererAfterPosition(root.selectionEnd(), root.selectionEndPos());
</span><span class="lines">@@ -936,11 +954,11 @@
</span><span class="cx">         if ((os-&gt;canBeSelectionLeaf() || os == root.selectionStart() || os == root.selectionEnd())
</span><span class="cx">             &amp;&amp; os-&gt;selectionState() != SelectionNone) {
</span><span class="cx">             // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
</span><del>-            oldSelectedObjects.set(os, std::make_unique&lt;RenderSelectionInfo&gt;(os, true));
</del><ins>+            oldSelectionData.selectedObjects.set(os, std::make_unique&lt;RenderSelectionInfo&gt;(os, true));
</ins><span class="cx">             if (blockRepaintMode == RepaintNewXOROld) {
</span><span class="cx">                 RenderBlock* cb = os-&gt;containingBlock();
</span><span class="cx">                 while (cb &amp;&amp; !cb-&gt;isRenderView()) {
</span><del>-                    std::unique_ptr&lt;RenderBlockSelectionInfo&gt;&amp; blockInfo = oldSelectedBlocks.add(cb, nullptr).iterator-&gt;value;
</del><ins>+                    std::unique_ptr&lt;RenderBlockSelectionInfo&gt;&amp; blockInfo = oldSelectionData.selectedBlocks.add(cb, nullptr).iterator-&gt;value;
</ins><span class="cx">                     if (blockInfo)
</span><span class="cx">                         break;
</span><span class="cx">                     blockInfo = std::make_unique&lt;RenderBlockSelectionInfo&gt;(cb);
</span><span class="lines">@@ -952,17 +970,13 @@
</span><span class="cx">         os = selectionIterator.next();
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Now clear the selection.
-    SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
-    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
</del><ins>+    auto oldObjectsEnd = oldSelectionData.selectedObjects.end();
+    for (auto i = oldSelectionData.selectedObjects.begin(); i != oldObjectsEnd; ++i)
</ins><span class="cx">         i-&gt;key-&gt;setSelectionStateIfNeeded(SelectionNone);
</span><ins>+}
</ins><span class="cx"> 
</span><del>-    // set selection start and end
-    root.setSelectionStart(start);
-    root.setSelectionStartPos(startPos);
-    root.setSelectionEnd(end);
-    root.setSelectionEndPos(endPos);
-
</del><ins>+void RenderView::applySubtreeSelection(SelectionSubtreeRoot&amp; root, RenderObject* start, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode, const OldSelectionData&amp; oldSelectionData)
+{
</ins><span class="cx">     // Update the selection status of all objects between selectionStart and selectionEnd
</span><span class="cx">     if (start &amp;&amp; start == end)
</span><span class="cx">         start-&gt;setSelectionStateIfNeeded(SelectionBoth);
</span><span class="lines">@@ -974,8 +988,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     RenderObject* o = start;
</span><del>-    stop = rendererAfterPosition(end, endPos);
-    selectionIterator = SelectionIterator(o);
</del><ins>+    RenderObject* stop = rendererAfterPosition(end, endPos);
+    SelectionIterator selectionIterator(o);
</ins><span class="cx">     
</span><span class="cx">     while (o &amp;&amp; o != stop) {
</span><span class="cx">         if (o != start &amp;&amp; o != end &amp;&amp; o-&gt;canBeSelectionLeaf())
</span><span class="lines">@@ -988,6 +1002,8 @@
</span><span class="cx"> 
</span><span class="cx">     // Now that the selection state has been updated for the new objects, walk them again and
</span><span class="cx">     // put them in the new objects list.
</span><ins>+    SelectedObjectMap newSelectedObjects;
+    SelectedBlockMap newSelectedBlocks;
</ins><span class="cx">     o = start;
</span><span class="cx">     selectionIterator = SelectionIterator(o);
</span><span class="cx">     while (o &amp;&amp; o != stop) {
</span><span class="lines">@@ -1022,13 +1038,14 @@
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     // Have any of the old selected objects changed compared to the new selection?
</span><del>-    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
-        RenderObject* obj = i-&gt;key;
</del><ins>+    auto oldObjectsEnd = oldSelectionData.selectedObjects.end();
+    for (auto it = oldSelectionData.selectedObjects.begin(); it != oldObjectsEnd; ++it) {
+        RenderObject* obj = it-&gt;key;
</ins><span class="cx">         RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
</span><del>-        RenderSelectionInfo* oldInfo = i-&gt;value.get();
</del><ins>+        RenderSelectionInfo* oldInfo = it-&gt;value.get();
</ins><span class="cx">         if (!newInfo || oldInfo-&gt;rect() != newInfo-&gt;rect() || oldInfo-&gt;state() != newInfo-&gt;state()
</span><del>-            || (root.selectionStart() == obj &amp;&amp; oldStartPos != root.selectionStartPos())
-            || (root.selectionEnd() == obj &amp;&amp; oldEndPos != root.selectionEndPos())) {
</del><ins>+            || (root.selectionStart() == obj &amp;&amp; oldSelectionData.selectionStartPos != root.selectionStartPos())
+            || (root.selectionEnd() == obj &amp;&amp; oldSelectionData.selectionEndPos != root.selectionEndPos())) {
</ins><span class="cx">             oldInfo-&gt;repaint();
</span><span class="cx">             if (newInfo) {
</span><span class="cx">                 newInfo-&gt;repaint();
</span><span class="lines">@@ -1038,16 +1055,16 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
</span><del>-    SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
-    for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)
-        i-&gt;value-&gt;repaint();
</del><ins>+    auto newObjectsEnd = newSelectedObjects.end();
+    for (auto it = newSelectedObjects.begin(); it != newObjectsEnd; ++it)
+        it-&gt;value-&gt;repaint();
</ins><span class="cx"> 
</span><span class="cx">     // Have any of the old blocks changed?
</span><del>-    SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
-    for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
-        RenderBlock* block = i-&gt;key;
</del><ins>+    auto oldBlocksEnd = oldSelectionData.selectedBlocks.end();
+    for (auto it = oldSelectionData.selectedBlocks.begin(); it != oldBlocksEnd; ++it) {
+        RenderBlock* block = it-&gt;key;
</ins><span class="cx">         RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
</span><del>-        RenderBlockSelectionInfo* oldInfo = i-&gt;value.get();
</del><ins>+        RenderBlockSelectionInfo* oldInfo = it-&gt;value.get();
</ins><span class="cx">         if (!newInfo || oldInfo-&gt;rects() != newInfo-&gt;rects() || oldInfo-&gt;state() != newInfo-&gt;state()) {
</span><span class="cx">             oldInfo-&gt;repaint();
</span><span class="cx">             if (newInfo) {
</span><span class="lines">@@ -1058,9 +1075,9 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
</span><del>-    SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
-    for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)
-        i-&gt;value-&gt;repaint();
</del><ins>+    auto newBlocksEnd = newSelectedBlocks.end();
+    for (auto it = newSelectedBlocks.begin(); it != newBlocksEnd; ++it)
+        it-&gt;value-&gt;repaint();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RenderView::getSelection(RenderObject*&amp; startRenderer, int&amp; startOffset, RenderObject*&amp; endRenderer, int&amp; endOffset) const
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderView.h (171675 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderView.h        2014-07-28 09:48:44 UTC (rev 171675)
+++ trunk/Source/WebCore/rendering/RenderView.h        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -304,7 +304,9 @@
</span><span class="cx">     friend class LayoutStateDisabler;
</span><span class="cx"> 
</span><span class="cx">     void splitSelectionBetweenSubtrees(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode);
</span><del>-    void setSubtreeSelection(SelectionSubtreeRoot&amp;, RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode);
</del><ins>+    void clearSubtreeSelection(const SelectionSubtreeRoot&amp;, SelectionRepaintMode, OldSelectionData&amp;);
+    void updateSelectionForSubtrees(RenderSubtreesMap&amp;, SelectionRepaintMode);
+    void applySubtreeSelection(SelectionSubtreeRoot&amp;, RenderObject* start, RenderObject* end, int endPos, SelectionRepaintMode, const OldSelectionData&amp;);
</ins><span class="cx">     LayoutRect subtreeSelectionBounds(const SelectionSubtreeRoot&amp;, bool clipToVisibleContent = true) const;
</span><span class="cx">     void repaintSubtreeSelection(const SelectionSubtreeRoot&amp;) const;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingSelectionSubtreeRootcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp (171675 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp        2014-07-28 09:48:44 UTC (rev 171675)
+++ trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -45,6 +45,14 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+SelectionSubtreeRoot::SelectionSubtreeRoot(RenderObject* selectionStart, int selectionStartPos, RenderObject* selectionEnd, int selectionEndPos)
+    : m_selectionStart(selectionStart)
+    , m_selectionStartPos(selectionStartPos)
+    , m_selectionEnd(selectionEnd)
+    , m_selectionEndPos(selectionEndPos)
+{
+}
+
</ins><span class="cx"> void SelectionSubtreeRoot::adjustForVisibleSelection(Document&amp; document)
</span><span class="cx"> {
</span><span class="cx">     if (selectionClear())
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingSelectionSubtreeRooth"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h (171675 => 171676)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h        2014-07-28 09:48:44 UTC (rev 171675)
+++ trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h        2014-07-28 13:19:22 UTC (rev 171676)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #define SelectionSubtreeRoot_h
</span><span class="cx"> 
</span><span class="cx"> #include &quot;RenderObject.h&quot;
</span><ins>+#include &quot;RenderSelectionInfo.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="cx"> 
</span><span class="lines">@@ -38,8 +39,28 @@
</span><span class="cx"> 
</span><span class="cx"> class SelectionSubtreeRoot {
</span><span class="cx"> public:
</span><ins>+    
+    typedef HashMap&lt;RenderObject*, std::unique_ptr&lt;RenderSelectionInfo&gt;&gt; SelectedObjectMap;
+    typedef HashMap&lt;RenderBlock*, std::unique_ptr&lt;RenderBlockSelectionInfo&gt;&gt; SelectedBlockMap;
+    typedef HashMap&lt;SelectionSubtreeRoot*, SelectionSubtreeRoot&gt; RenderSubtreesMap;
</ins><span class="cx"> 
</span><ins>+    struct OldSelectionData {
+        OldSelectionData()
+            : selectionStartPos(-1)
+            , selectionEndPos(-1)
+        {
+        }
+
+        int selectionStartPos;
+        int selectionEndPos;
+        SelectedObjectMap selectedObjects;
+        SelectedBlockMap selectedBlocks;
+    };
+    
+    typedef HashMap&lt;SelectionSubtreeRoot*, std::unique_ptr&lt;OldSelectionData&gt;&gt; SubtreeOldSelectionDataMap;
+
</ins><span class="cx">     SelectionSubtreeRoot();
</span><ins>+    SelectionSubtreeRoot(RenderObject* selectionStart, int selectionStartPos, RenderObject* selectionEnd, int selectionEndPos);
</ins><span class="cx"> 
</span><span class="cx">     RenderObject* selectionStart() const { return m_selectionStart; }
</span><span class="cx">     int selectionStartPos() const { return m_selectionStartPos; }
</span></span></pre>
</div>
</div>

</body>
</html>