Title: [171218] trunk
Revision
171218
Author
k...@webkit.org
Date
2014-07-18 02:50:01 -0700 (Fri, 18 Jul 2014)

Log Message

REGRESSION (r169105): Crash in selection
https://bugs.webkit.org/show_bug.cgi?id=134303

Patch by Radu Stavila <stav...@adobe.com> on 2014-07-18
Reviewed by Ryosuke Niwa.

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 "clear" and an "apply" method. The updateSelectionForSubtrees
method first iterates through all subtrees and performs the "clear" method and then starts all over again
and performs the "apply" method.

Also, the selectionStart/End members in RenderView have been renamed to fix problems caused by the fact that
RenderView inherits SelectionSubtreeRoot, which also has the same selectionStart/End members.

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

* WebCore.xcodeproj/project.pbxproj:
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::isSelectionRoot):
* rendering/RenderSelectionInfo.h:
* rendering/RenderView.cpp:
(WebCore::RenderView::RenderView):
(WebCore::RenderView::setSelection): Renamed m_selectionStart/End to m_unsplitSelectionStart/End
(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::getSelection): Renamed m_selectionStart/End to m_unsplitSelectionStart/End
(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.

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

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (171217 => 171218)


--- trunk/LayoutTests/ChangeLog	2014-07-18 07:13:36 UTC (rev 171217)
+++ trunk/LayoutTests/ChangeLog	2014-07-18 09:50:01 UTC (rev 171218)
@@ -1,3 +1,15 @@
+2014-07-18  Radu Stavila  <stav...@adobe.com>
+
+        REGRESSION (r169105): Crash in selection
+        https://bugs.webkit.org/show_bug.cgi?id=134303
+
+        Reviewed by Ryosuke Niwa.
+
+        Added test for the crash that occurred in some cases when selecting.
+
+        * fast/regions/selection/crash-deselect-expected.txt: Added.
+        * fast/regions/selection/crash-deselect.html: Added.
+
 2014-07-17  Zalan Bujtas  <za...@apple.com>
 
         Subpixel rendering: Embedded non-compositing rotate transform paints to wrong position.

Added: trunk/LayoutTests/fast/regions/selection/crash-deselect-expected.txt (0 => 171218)


--- trunk/LayoutTests/fast/regions/selection/crash-deselect-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/regions/selection/crash-deselect-expected.txt	2014-07-18 09:50:01 UTC (rev 171218)
@@ -0,0 +1,5 @@
+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: 
+

Added: trunk/LayoutTests/fast/regions/selection/crash-deselect.html (0 => 171218)


--- trunk/LayoutTests/fast/regions/selection/crash-deselect.html	                        (rev 0)
+++ trunk/LayoutTests/fast/regions/selection/crash-deselect.html	2014-07-18 09:50:01 UTC (rev 171218)
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html id="webtest0">
+    <head id="webtest1">
+        <style id="webtest2"></style>
+        <style>
+            :last-child { -webkit-flow-into: foo; }
+        </style>
+        
+    </head>
+    <body id="webtest3">
+        <script id="example"></script>
+
+        <script type="text/_javascript_">
+            if (window.testRunner)
+                testRunner.dumpAsText(false);
+        </script>
+
+        <script>
+            var new_elem = document.createElement("canvas");
+            new_elem.setAttribute("id", "webtest11");
+            document.querySelector("#webtest0").appendChild(new_elem);
+
+            document.write("<br><summary>");
+        </script>
+        <summary>
+            <mathml id="webtest12">
+                <femerge></femerge>
+            </mathml>
+
+            <script>
+                function selectionTest() {
+                    try {
+                        wf_i = 0;
+                        for (; wf_i<40; wf_i++) {
+                            var range = document.createRange();
+
+                            range.setStartBefore(document.getElementById("webtest3"));
+                            range.setEndAfter(document.getElementById("webtest2"));
+                            range.deleteContents();
+                            
+                            var markElement = document.getElementById("webtest1").appendChild(document.createElementNS("", "mark"));
+                            range.setStartAfter(markElement);
+
+                            var appletElement = document.getElementById("example").appendChild(document.createElement("applet"));
+                            range.setEndAfter(appletElement);
+
+                            range.insertNode(document.getElementById("example"));
+                        }
+                    } catch(e) {
+                      document.write("Errlog selectionTest: " + e.name + ": " + e.message + " : index " + wf_i + " <br><table/>");
+                    }
+                }
+                selectionTest();
+            </script>
+            <sub>
+
+            <script>
+                document.designMode = "on";
+                document.execCommand("SelectAll");
+                document.write("Errlog webtest_fn_24: <br><nobr>");
+
+                var femergeElement = document.getElementById("webtest12").appendChild(document.createElement("femerge"));
+                var appletElement = document.getElementById("example").appendChild(document.createElement("applet"));
+                var gradientElement = document.body.appendChild(document.createElement("gradient"));
+                        
+                document.getElementById("webtest2").isEqualNode(femergeElement.insertBefore(document.documentElement, gradientElement));
+            </script>
+
+            <table></table>
+        </summary>
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (171217 => 171218)


--- trunk/Source/WebCore/ChangeLog	2014-07-18 07:13:36 UTC (rev 171217)
+++ trunk/Source/WebCore/ChangeLog	2014-07-18 09:50:01 UTC (rev 171218)
@@ -1,3 +1,43 @@
+2014-07-18  Radu Stavila  <stav...@adobe.com>
+
+        REGRESSION (r169105): Crash in selection
+        https://bugs.webkit.org/show_bug.cgi?id=134303
+
+        Reviewed by Ryosuke Niwa.
+
+        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 "clear" and an "apply" method. The updateSelectionForSubtrees
+        method first iterates through all subtrees and performs the "clear" method and then starts all over again
+        and performs the "apply" method.
+
+        Also, the selectionStart/End members in RenderView have been renamed to fix problems caused by the fact that
+        RenderView inherits SelectionSubtreeRoot, which also has the same selectionStart/End members.
+
+        Test: fast/regions/selection/crash-deselect.html
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::isSelectionRoot):
+        * rendering/RenderSelectionInfo.h:
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::RenderView):
+        (WebCore::RenderView::setSelection): Renamed m_selectionStart/End to m_unsplitSelectionStart/End
+        (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::getSelection): Renamed m_selectionStart/End to m_unsplitSelectionStart/End
+        (WebCore::RenderView::setSubtreeSelection): Deleted.
+        * rendering/RenderView.h:
+        * rendering/SelectionSubtreeRoot.cpp:
+        (WebCore::SelectionSubtreeRoot::SelectionSubtreeRoot):
+        * rendering/SelectionSubtreeRoot.h:
+        (WebCore::SelectionSubtreeRoot::OldSelectionData::OldSelectionData):
+
 2014-07-17  Jer Noble  <jer.no...@apple.com>
 
         [MSE] Re-enqueue after a removeCodedFrames() only if the removed frames overlap what may have possibly been enqueued but undisplayed.

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (171217 => 171218)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2014-07-18 07:13:36 UTC (rev 171217)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2014-07-18 09:50:01 UTC (rev 171218)
@@ -466,7 +466,7 @@
 		0F09087F1444FDB200028917 /* ScrollbarTheme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE71415142189FC00DB33BA /* ScrollbarTheme.cpp */; };
 		0F099D0817B968A100FF84B9 /* WebCoreTypedArrayController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F099D0617B968A100FF84B9 /* WebCoreTypedArrayController.cpp */; };
 		0F099D0917B968A100FF84B9 /* WebCoreTypedArrayController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F099D0717B968A100FF84B9 /* WebCoreTypedArrayController.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		0F11A54F0F39233100C37884 /* RenderSelectionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F11A54E0F39233100C37884 /* RenderSelectionInfo.h */; };
+		0F11A54F0F39233100C37884 /* RenderSelectionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F11A54E0F39233100C37884 /* RenderSelectionInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F13163E16ED0CC80035CC04 /* PlatformCAFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13163D16ED0CC80035CC04 /* PlatformCAFilters.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		0F13164016ED0CDE0035CC04 /* PlatformCAFiltersMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F13163F16ED0CDE0035CC04 /* PlatformCAFiltersMac.mm */; };
 		0F15DA8A0F3AAEE70000CE47 /* AnimationControllerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15DA890F3AAEE70000CE47 /* AnimationControllerPrivate.h */; };

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (171217 => 171218)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2014-07-18 07:13:36 UTC (rev 171217)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2014-07-18 09:50:01 UTC (rev 171218)
@@ -1828,8 +1828,8 @@
         || isRenderFlowThread() || style().columnSpan() == ColumnSpanAll)
         return true;
     
-    if (view().selectionStart()) {
-        Node* startElement = view().selectionStart()->node();
+    if (view().selectionUnsplitStart()) {
+        Node* startElement = view().selectionUnsplitStart()->node();
         if (startElement && startElement->rootEditableElement() == element())
             return true;
     }

Modified: trunk/Source/WebCore/rendering/RenderSelectionInfo.h (171217 => 171218)


--- trunk/Source/WebCore/rendering/RenderSelectionInfo.h	2014-07-18 07:13:36 UTC (rev 171217)
+++ trunk/Source/WebCore/rendering/RenderSelectionInfo.h	2014-07-18 09:50:01 UTC (rev 171218)
@@ -25,8 +25,9 @@
 #ifndef RenderSelectionInfo_h
 #define RenderSelectionInfo_h
 
+#include "GapRects.h"
 #include "IntRect.h"
-#include "RenderBox.h"
+#include "RenderBlock.h"
 #include "RenderText.h"
 
 namespace WebCore {

Modified: trunk/Source/WebCore/rendering/RenderView.cpp (171217 => 171218)


--- trunk/Source/WebCore/rendering/RenderView.cpp	2014-07-18 07:13:36 UTC (rev 171217)
+++ trunk/Source/WebCore/rendering/RenderView.cpp	2014-07-18 09:50:01 UTC (rev 171218)
@@ -96,10 +96,10 @@
 RenderView::RenderView(Document& document, PassRef<RenderStyle> style)
     : RenderBlockFlow(document, WTF::move(style))
     , m_frameView(*document.view())
-    , m_selectionStart(0)
-    , m_selectionEnd(0)
-    , m_selectionStartPos(-1)
-    , m_selectionEndPos(-1)
+    , m_unsplitSelectionStart(0)
+    , m_unsplitSelectionEnd(0)
+    , m_unsplitSelectionStartPos(-1)
+    , m_unsplitSelectionEndPos(-1)
     , m_rendererCount(0)
     , m_maximalOutlineSize(0)
     , m_lazyRepaintTimer(this, &RenderView::lazyRepaintTimerFired)
@@ -842,19 +842,22 @@
     bool caretChanged = m_selectionWasCaret != frame().selection().isCaret();
     m_selectionWasCaret = frame().selection().isCaret();
     // Just return if the selection hasn't changed.
-    if (m_selectionStart == start && m_selectionStartPos == startPos &&
-        m_selectionEnd == end && m_selectionEndPos == endPos && !caretChanged)
+    if (m_unsplitSelectionStart == start && m_unsplitSelectionStartPos == startPos
+        && m_unsplitSelectionEnd == end && m_unsplitSelectionEndPos == endPos && !caretChanged) {
         return;
+    }
 
     // Set global positions for new selection.
-    m_selectionStart = start;
-    m_selectionStartPos = startPos;
-    m_selectionEnd = end;
-    m_selectionEndPos = endPos;
+    m_unsplitSelectionStart = start;
+    m_unsplitSelectionStartPos = startPos;
+    m_unsplitSelectionEnd = end;
+    m_unsplitSelectionEndPos = endPos;
 
     // If there is no RenderNamedFlowThreads we follow the regular selection.
     if (!hasRenderNamedFlowThreads()) {
-        setSubtreeSelection(*this, start, startPos, end, endPos, blockRepaintMode);
+        RenderSubtreesMap singleSubtreeMap;
+        singleSubtreeMap.set(this, SelectionSubtreeRoot(start, startPos, end, endPos));
+        updateSelectionForSubtrees(singleSubtreeMap, blockRepaintMode);
         return;
     }
 
@@ -864,7 +867,6 @@
 void RenderView::splitSelectionBetweenSubtrees(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
 {
     // Compute the visible selection end points for each of the subtrees.
-    typedef HashMap<SelectionSubtreeRoot*, SelectionSubtreeRoot> RenderSubtreesMap;
     RenderSubtreesMap renderSubtreesMap;
 
     SelectionSubtreeRoot initialSelection;
@@ -898,33 +900,49 @@
             renderSubtreesMap.set(&root, selectionData);
         }
     }
+    
+    updateSelectionForSubtrees(renderSubtreesMap, blockRepaintMode);
+}
 
-    for (RenderSubtreesMap::iterator i = renderSubtreesMap.begin(); i != renderSubtreesMap.end(); ++i) {
-        SelectionSubtreeRoot subtreeSelectionData = i->value;
+void RenderView::updateSelectionForSubtrees(RenderSubtreesMap& renderSubtreesMap, SelectionRepaintMode blockRepaintMode)
+{
+    SubtreeOldSelectionDataMap oldSelectionDataMap;
+    for (auto it = renderSubtreesMap.begin(); it != renderSubtreesMap.end(); ++it) {
+        std::unique_ptr<OldSelectionData> oldSelectionData = std::make_unique<OldSelectionData>();
+        clearSubtreeSelection(*it->key, blockRepaintMode, *oldSelectionData);
+        oldSelectionDataMap.set(it->key, std::move(oldSelectionData));
+
+        SelectionSubtreeRoot& subtreeSelectionData = it->value;
         subtreeSelectionData.adjustForVisibleSelection(document());
-        setSubtreeSelection(*i->key, subtreeSelectionData.selectionStart(), subtreeSelectionData.selectionStartPos(),
-            subtreeSelectionData.selectionEnd(), subtreeSelectionData.selectionEndPos(), blockRepaintMode);
+        
+        SelectionSubtreeRoot& root = *it->key;
+        root.setSelectionStart(subtreeSelectionData.selectionStart());
+        root.setSelectionStartPos(subtreeSelectionData.selectionStartPos());
+        root.setSelectionEnd(subtreeSelectionData.selectionEnd());
+        root.setSelectionEndPos(subtreeSelectionData.selectionEndPos());
     }
+
+    // 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->value;
+        OldSelectionData& oldSelectionData = *oldSelectionDataMap.get(it->key);
+        applySubtreeSelection(*it->key, subtreeSelectionData.selectionStart(), subtreeSelectionData.selectionEnd(), subtreeSelectionData.selectionEndPos(), blockRepaintMode, oldSelectionData);
+    }
 }
 
-void RenderView::setSubtreeSelection(SelectionSubtreeRoot& root, RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
+void RenderView::clearSubtreeSelection(const SelectionSubtreeRoot& root, SelectionRepaintMode blockRepaintMode, OldSelectionData& oldSelectionData)
 {
     // Record the old selected objects.  These will be used later
     // when we compare against the new selected objects.
-    int oldStartPos = root.selectionStartPos();
-    int oldEndPos = root.selectionEndPos();
-
-    // Objects each have a single selection rect to examine.
-    typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectedObjectMap;
-    SelectedObjectMap oldSelectedObjects;
-    SelectedObjectMap newSelectedObjects;
-
+    oldSelectionData.selectionStartPos = root.selectionStartPos();
+    oldSelectionData.selectionEndPos = root.selectionEndPos();
+    
     // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks.
     // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise
     // the union of those rects might remain the same even when changes have occurred.
-    typedef HashMap<RenderBlock*, std::unique_ptr<RenderBlockSelectionInfo>> SelectedBlockMap;
-    SelectedBlockMap oldSelectedBlocks;
-    SelectedBlockMap newSelectedBlocks;
 
     RenderObject* os = root.selectionStart();
     RenderObject* stop = rendererAfterPosition(root.selectionEnd(), root.selectionEndPos());
@@ -933,11 +951,11 @@
         if ((os->canBeSelectionLeaf() || os == root.selectionStart() || os == root.selectionEnd())
             && os->selectionState() != SelectionNone) {
             // Blocks are responsible for painting line gaps and margin gaps.  They must be examined as well.
-            oldSelectedObjects.set(os, std::make_unique<RenderSelectionInfo>(os, true));
+            oldSelectionData.selectedObjects.set(os, std::make_unique<RenderSelectionInfo>(os, true));
             if (blockRepaintMode == RepaintNewXOROld) {
                 RenderBlock* cb = os->containingBlock();
                 while (cb && !cb->isRenderView()) {
-                    std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).iterator->value;
+                    std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = oldSelectionData.selectedBlocks.add(cb, nullptr).iterator->value;
                     if (blockInfo)
                         break;
                     blockInfo = std::make_unique<RenderBlockSelectionInfo>(cb);
@@ -949,17 +967,13 @@
         os = selectionIterator.next();
     }
 
-    // Now clear the selection.
-    SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end();
-    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i)
+    auto oldObjectsEnd = oldSelectionData.selectedObjects.end();
+    for (auto i = oldSelectionData.selectedObjects.begin(); i != oldObjectsEnd; ++i)
         i->key->setSelectionStateIfNeeded(SelectionNone);
+}
 
-    // set selection start and end
-    root.setSelectionStart(start);
-    root.setSelectionStartPos(startPos);
-    root.setSelectionEnd(end);
-    root.setSelectionEndPos(endPos);
-
+void RenderView::applySubtreeSelection(SelectionSubtreeRoot& root, RenderObject* start, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode, const OldSelectionData& oldSelectionData)
+{
     // Update the selection status of all objects between selectionStart and selectionEnd
     if (start && start == end)
         start->setSelectionStateIfNeeded(SelectionBoth);
@@ -971,8 +985,8 @@
     }
 
     RenderObject* o = start;
-    stop = rendererAfterPosition(end, endPos);
-    selectionIterator = SelectionIterator(o);
+    RenderObject* stop = rendererAfterPosition(end, endPos);
+    SelectionIterator selectionIterator(o);
     
     while (o && o != stop) {
         if (o != start && o != end && o->canBeSelectionLeaf())
@@ -985,6 +999,8 @@
 
     // Now that the selection state has been updated for the new objects, walk them again and
     // put them in the new objects list.
+    SelectedObjectMap newSelectedObjects;
+    SelectedBlockMap newSelectedBlocks;
     o = start;
     selectionIterator = SelectionIterator(o);
     while (o && o != stop) {
@@ -1019,13 +1035,14 @@
         return;
 
     // Have any of the old selected objects changed compared to the new selection?
-    for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) {
-        RenderObject* obj = i->key;
+    auto oldObjectsEnd = oldSelectionData.selectedObjects.end();
+    for (auto it = oldSelectionData.selectedObjects.begin(); it != oldObjectsEnd; ++it) {
+        RenderObject* obj = it->key;
         RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
-        RenderSelectionInfo* oldInfo = i->value.get();
+        RenderSelectionInfo* oldInfo = it->value.get();
         if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state()
-            || (root.selectionStart() == obj && oldStartPos != root.selectionStartPos())
-            || (root.selectionEnd() == obj && oldEndPos != root.selectionEndPos())) {
+            || (root.selectionStart() == obj && oldSelectionData.selectionStartPos != root.selectionStartPos())
+            || (root.selectionEnd() == obj && oldSelectionData.selectionEndPos != root.selectionEndPos())) {
             oldInfo->repaint();
             if (newInfo) {
                 newInfo->repaint();
@@ -1035,16 +1052,16 @@
     }
 
     // Any new objects that remain were not found in the old objects dict, and so they need to be updated.
-    SelectedObjectMap::iterator newObjectsEnd = newSelectedObjects.end();
-    for (SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)
-        i->value->repaint();
+    auto newObjectsEnd = newSelectedObjects.end();
+    for (auto it = newSelectedObjects.begin(); it != newObjectsEnd; ++it)
+        it->value->repaint();
 
     // Have any of the old blocks changed?
-    SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
-    for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
-        RenderBlock* block = i->key;
+    auto oldBlocksEnd = oldSelectionData.selectedBlocks.end();
+    for (auto it = oldSelectionData.selectedBlocks.begin(); it != oldBlocksEnd; ++it) {
+        RenderBlock* block = it->key;
         RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
-        RenderBlockSelectionInfo* oldInfo = i->value.get();
+        RenderBlockSelectionInfo* oldInfo = it->value.get();
         if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
             oldInfo->repaint();
             if (newInfo) {
@@ -1055,17 +1072,17 @@
     }
 
     // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated.
-    SelectedBlockMap::iterator newBlocksEnd = newSelectedBlocks.end();
-    for (SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)
-        i->value->repaint();
+    auto newBlocksEnd = newSelectedBlocks.end();
+    for (auto it = newSelectedBlocks.begin(); it != newBlocksEnd; ++it)
+        it->value->repaint();
 }
 
 void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const
 {
-    startRenderer = m_selectionStart;
-    startOffset = m_selectionStartPos;
-    endRenderer = m_selectionEnd;
-    endOffset = m_selectionEndPos;
+    startRenderer = m_unsplitSelectionStart;
+    startOffset = m_unsplitSelectionStartPos;
+    endRenderer = m_unsplitSelectionEnd;
+    endOffset = m_unsplitSelectionEndPos;
 }
 
 void RenderView::clearSelection()

Modified: trunk/Source/WebCore/rendering/RenderView.h (171217 => 171218)


--- trunk/Source/WebCore/rendering/RenderView.h	2014-07-18 07:13:36 UTC (rev 171217)
+++ trunk/Source/WebCore/rendering/RenderView.h	2014-07-18 09:50:01 UTC (rev 171218)
@@ -89,8 +89,8 @@
     void setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode = RepaintNewXOROld);
     void getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const;
     void clearSelection();
-    RenderObject* selectionStart() const { return m_selectionStart; }
-    RenderObject* selectionEnd() const { return m_selectionEnd; }
+    RenderObject* selectionUnsplitStart() const { return m_unsplitSelectionStart; }
+    RenderObject* selectionUnsplitEnd() const { return m_unsplitSelectionEnd; }
     IntRect selectionBounds(bool clipToVisibleContent = true) const;
     void repaintSelection() const;
 
@@ -304,17 +304,19 @@
     friend class LayoutStateDisabler;
 
     void splitSelectionBetweenSubtrees(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode);
-    void setSubtreeSelection(SelectionSubtreeRoot&, RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode);
+    void clearSubtreeSelection(const SelectionSubtreeRoot&, SelectionRepaintMode, OldSelectionData&);
+    void updateSelectionForSubtrees(RenderSubtreesMap&, SelectionRepaintMode);
+    void applySubtreeSelection(SelectionSubtreeRoot&, RenderObject* start, RenderObject* end, int endPos, SelectionRepaintMode, const OldSelectionData&);
     LayoutRect subtreeSelectionBounds(const SelectionSubtreeRoot&, bool clipToVisibleContent = true) const;
     void repaintSubtreeSelection(const SelectionSubtreeRoot&) const;
 
 private:
     FrameView& m_frameView;
 
-    RenderObject* m_selectionStart;
-    RenderObject* m_selectionEnd;
-    int m_selectionStartPos;
-    int m_selectionEndPos;
+    RenderObject* m_unsplitSelectionStart;
+    RenderObject* m_unsplitSelectionEnd;
+    int m_unsplitSelectionStartPos;
+    int m_unsplitSelectionEndPos;
 
     uint64_t m_rendererCount;
 

Modified: trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp (171217 => 171218)


--- trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp	2014-07-18 07:13:36 UTC (rev 171217)
+++ trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp	2014-07-18 09:50:01 UTC (rev 171218)
@@ -45,6 +45,14 @@
 {
 }
 
+SelectionSubtreeRoot::SelectionSubtreeRoot(RenderObject* selectionStart, int selectionStartPos, RenderObject* selectionEnd, int selectionEndPos)
+    : m_selectionStart(selectionStart)
+    , m_selectionStartPos(selectionStartPos)
+    , m_selectionEnd(selectionEnd)
+    , m_selectionEndPos(selectionEndPos)
+{
+}
+
 void SelectionSubtreeRoot::adjustForVisibleSelection(Document& document)
 {
     if (selectionClear())

Modified: trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h (171217 => 171218)


--- trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h	2014-07-18 07:13:36 UTC (rev 171217)
+++ trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h	2014-07-18 09:50:01 UTC (rev 171218)
@@ -31,6 +31,7 @@
 #define SelectionSubtreeRoot_h
 
 #include "RenderObject.h"
+#include "RenderSelectionInfo.h"
 
 namespace WebCore {
 
@@ -38,8 +39,28 @@
 
 class SelectionSubtreeRoot {
 public:
+    
+    typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectedObjectMap;
+    typedef HashMap<RenderBlock*, std::unique_ptr<RenderBlockSelectionInfo>> SelectedBlockMap;
+    typedef HashMap<SelectionSubtreeRoot*, SelectionSubtreeRoot> RenderSubtreesMap;
 
+    struct OldSelectionData {
+        OldSelectionData()
+            : selectionStartPos(-1)
+            , selectionEndPos(-1)
+        {
+        }
+
+        int selectionStartPos;
+        int selectionEndPos;
+        SelectedObjectMap selectedObjects;
+        SelectedBlockMap selectedBlocks;
+    };
+    
+    typedef HashMap<SelectionSubtreeRoot*, std::unique_ptr<OldSelectionData>> SubtreeOldSelectionDataMap;
+
     SelectionSubtreeRoot();
+    SelectionSubtreeRoot(RenderObject* selectionStart, int selectionStartPos, RenderObject* selectionEnd, int selectionEndPos);
 
     RenderObject* selectionStart() const { return m_selectionStart; }
     int selectionStartPos() const { return m_selectionStartPos; }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to