Changeset 171218 in webkit
- Timestamp:
- Jul 18, 2014 2:50:01 AM (10 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r171210 r171218 1 2014-07-18 Radu Stavila <stavila@adobe.com> 2 3 REGRESSION (r169105): Crash in selection 4 https://bugs.webkit.org/show_bug.cgi?id=134303 5 6 Reviewed by Ryosuke Niwa. 7 8 Added test for the crash that occurred in some cases when selecting. 9 10 * fast/regions/selection/crash-deselect-expected.txt: Added. 11 * fast/regions/selection/crash-deselect.html: Added. 12 1 13 2014-07-17 Zalan Bujtas <zalan@apple.com> 2 14 -
trunk/Source/WebCore/ChangeLog
r171215 r171218 1 2014-07-18 Radu Stavila <stavila@adobe.com> 2 3 REGRESSION (r169105): Crash in selection 4 https://bugs.webkit.org/show_bug.cgi?id=134303 5 6 Reviewed by Ryosuke Niwa. 7 8 When splitting the selection between different subtrees, all subtrees must have their selection cleared before 9 starting to apply the new selection. Otherwise, when selecting objects in a named flow thread and going up 10 its containing block chain, we can end up in the view's selection root, which has not yet been updated and so 11 we get inconsistent data. 12 13 To achieve this goal, the selection update was split into a "clear" and an "apply" method. The updateSelectionForSubtrees 14 method first iterates through all subtrees and performs the "clear" method and then starts all over again 15 and performs the "apply" method. 16 17 Also, the selectionStart/End members in RenderView have been renamed to fix problems caused by the fact that 18 RenderView inherits SelectionSubtreeRoot, which also has the same selectionStart/End members. 19 20 Test: fast/regions/selection/crash-deselect.html 21 22 * WebCore.xcodeproj/project.pbxproj: 23 * rendering/RenderBlock.cpp: 24 (WebCore::RenderBlock::isSelectionRoot): 25 * rendering/RenderSelectionInfo.h: 26 * rendering/RenderView.cpp: 27 (WebCore::RenderView::RenderView): 28 (WebCore::RenderView::setSelection): Renamed m_selectionStart/End to m_unsplitSelectionStart/End 29 (WebCore::RenderView::splitSelectionBetweenSubtrees): 30 (WebCore::RenderView::updateSelectionForSubtrees): Added, clears and re-applies selection for all selection subtrees. 31 (WebCore::RenderView::clearSubtreeSelection): Added, clears selection and returns previously selected information. 32 (WebCore::RenderView::applySubtreeSelection): Added, updates the selection status of all objects inside the selection tree, compares old and new data and repaints accordingly. 33 (WebCore::RenderView::getSelection): Renamed m_selectionStart/End to m_unsplitSelectionStart/End 34 (WebCore::RenderView::setSubtreeSelection): Deleted. 35 * rendering/RenderView.h: 36 * rendering/SelectionSubtreeRoot.cpp: 37 (WebCore::SelectionSubtreeRoot::SelectionSubtreeRoot): 38 * rendering/SelectionSubtreeRoot.h: 39 (WebCore::SelectionSubtreeRoot::OldSelectionData::OldSelectionData): 40 1 41 2014-07-17 Jer Noble <jer.noble@apple.com> 2 42 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r171188 r171218 467 467 0F099D0817B968A100FF84B9 /* WebCoreTypedArrayController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F099D0617B968A100FF84B9 /* WebCoreTypedArrayController.cpp */; }; 468 468 0F099D0917B968A100FF84B9 /* WebCoreTypedArrayController.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F099D0717B968A100FF84B9 /* WebCoreTypedArrayController.h */; settings = {ATTRIBUTES = (Private, ); }; }; 469 0F11A54F0F39233100C37884 /* RenderSelectionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F11A54E0F39233100C37884 /* RenderSelectionInfo.h */; };469 0F11A54F0F39233100C37884 /* RenderSelectionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F11A54E0F39233100C37884 /* RenderSelectionInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 470 470 0F13163E16ED0CC80035CC04 /* PlatformCAFilters.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F13163D16ED0CC80035CC04 /* PlatformCAFilters.h */; settings = {ATTRIBUTES = (Private, ); }; }; 471 471 0F13164016ED0CDE0035CC04 /* PlatformCAFiltersMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0F13163F16ED0CDE0035CC04 /* PlatformCAFiltersMac.mm */; }; -
trunk/Source/WebCore/rendering/RenderBlock.cpp
r170871 r171218 1829 1829 return true; 1830 1830 1831 if (view().selection Start()) {1832 Node* startElement = view().selection Start()->node();1831 if (view().selectionUnsplitStart()) { 1832 Node* startElement = view().selectionUnsplitStart()->node(); 1833 1833 if (startElement && startElement->rootEditableElement() == element()) 1834 1834 return true; -
trunk/Source/WebCore/rendering/RenderSelectionInfo.h
r170758 r171218 26 26 #define RenderSelectionInfo_h 27 27 28 #include "GapRects.h" 28 29 #include "IntRect.h" 29 #include "RenderB ox.h"30 #include "RenderBlock.h" 30 31 #include "RenderText.h" 31 32 -
trunk/Source/WebCore/rendering/RenderView.cpp
r170774 r171218 97 97 : RenderBlockFlow(document, WTF::move(style)) 98 98 , m_frameView(*document.view()) 99 , m_ selectionStart(0)100 , m_ selectionEnd(0)101 , m_ selectionStartPos(-1)102 , m_ selectionEndPos(-1)99 , m_unsplitSelectionStart(0) 100 , m_unsplitSelectionEnd(0) 101 , m_unsplitSelectionStartPos(-1) 102 , m_unsplitSelectionEndPos(-1) 103 103 , m_rendererCount(0) 104 104 , m_maximalOutlineSize(0) … … 843 843 m_selectionWasCaret = frame().selection().isCaret(); 844 844 // Just return if the selection hasn't changed. 845 if (m_selectionStart == start && m_selectionStartPos == startPos && 846 m_selectionEnd == end && m_selectionEndPos == endPos && !caretChanged) 847 return; 845 if (m_unsplitSelectionStart == start && m_unsplitSelectionStartPos == startPos 846 && m_unsplitSelectionEnd == end && m_unsplitSelectionEndPos == endPos && !caretChanged) { 847 return; 848 } 848 849 849 850 // Set global positions for new selection. 850 m_ selectionStart = start;851 m_ selectionStartPos = startPos;852 m_ selectionEnd = end;853 m_ selectionEndPos = endPos;851 m_unsplitSelectionStart = start; 852 m_unsplitSelectionStartPos = startPos; 853 m_unsplitSelectionEnd = end; 854 m_unsplitSelectionEndPos = endPos; 854 855 855 856 // If there is no RenderNamedFlowThreads we follow the regular selection. 856 857 if (!hasRenderNamedFlowThreads()) { 857 setSubtreeSelection(*this, start, startPos, end, endPos, blockRepaintMode); 858 RenderSubtreesMap singleSubtreeMap; 859 singleSubtreeMap.set(this, SelectionSubtreeRoot(start, startPos, end, endPos)); 860 updateSelectionForSubtrees(singleSubtreeMap, blockRepaintMode); 858 861 return; 859 862 } … … 865 868 { 866 869 // Compute the visible selection end points for each of the subtrees. 867 typedef HashMap<SelectionSubtreeRoot*, SelectionSubtreeRoot> RenderSubtreesMap;868 870 RenderSubtreesMap renderSubtreesMap; 869 871 … … 899 901 } 900 902 } 901 902 for (RenderSubtreesMap::iterator i = renderSubtreesMap.begin(); i != renderSubtreesMap.end(); ++i) { 903 SelectionSubtreeRoot subtreeSelectionData = i->value; 903 904 updateSelectionForSubtrees(renderSubtreesMap, blockRepaintMode); 905 } 906 907 void RenderView::updateSelectionForSubtrees(RenderSubtreesMap& renderSubtreesMap, SelectionRepaintMode blockRepaintMode) 908 { 909 SubtreeOldSelectionDataMap oldSelectionDataMap; 910 for (auto it = renderSubtreesMap.begin(); it != renderSubtreesMap.end(); ++it) { 911 std::unique_ptr<OldSelectionData> oldSelectionData = std::make_unique<OldSelectionData>(); 912 clearSubtreeSelection(*it->key, blockRepaintMode, *oldSelectionData); 913 oldSelectionDataMap.set(it->key, std::move(oldSelectionData)); 914 915 SelectionSubtreeRoot& subtreeSelectionData = it->value; 904 916 subtreeSelectionData.adjustForVisibleSelection(document()); 905 setSubtreeSelection(*i->key, subtreeSelectionData.selectionStart(), subtreeSelectionData.selectionStartPos(), 906 subtreeSelectionData.selectionEnd(), subtreeSelectionData.selectionEndPos(), blockRepaintMode); 907 } 908 } 909 910 void RenderView::setSubtreeSelection(SelectionSubtreeRoot& root, RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode) 917 918 SelectionSubtreeRoot& root = *it->key; 919 root.setSelectionStart(subtreeSelectionData.selectionStart()); 920 root.setSelectionStartPos(subtreeSelectionData.selectionStartPos()); 921 root.setSelectionEnd(subtreeSelectionData.selectionEnd()); 922 root.setSelectionEndPos(subtreeSelectionData.selectionEndPos()); 923 } 924 925 // Update selection status for the objects inside the selection subtrees. 926 // This needs to be done after the previous loop updated the selectionStart/End 927 // parameters of all subtrees because we're going to be climbing up the containing 928 // block chain and we might end up in a different selection subtree. 929 for (auto it = renderSubtreesMap.begin(); it != renderSubtreesMap.end(); ++it) { 930 SelectionSubtreeRoot subtreeSelectionData = it->value; 931 OldSelectionData& oldSelectionData = *oldSelectionDataMap.get(it->key); 932 applySubtreeSelection(*it->key, subtreeSelectionData.selectionStart(), subtreeSelectionData.selectionEnd(), subtreeSelectionData.selectionEndPos(), blockRepaintMode, oldSelectionData); 933 } 934 } 935 936 void RenderView::clearSubtreeSelection(const SelectionSubtreeRoot& root, SelectionRepaintMode blockRepaintMode, OldSelectionData& oldSelectionData) 911 937 { 912 938 // Record the old selected objects. These will be used later 913 939 // when we compare against the new selected objects. 914 int oldStartPos = root.selectionStartPos(); 915 int oldEndPos = root.selectionEndPos(); 916 917 // Objects each have a single selection rect to examine. 918 typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectedObjectMap; 919 SelectedObjectMap oldSelectedObjects; 920 SelectedObjectMap newSelectedObjects; 921 940 oldSelectionData.selectionStartPos = root.selectionStartPos(); 941 oldSelectionData.selectionEndPos = root.selectionEndPos(); 942 922 943 // Blocks contain selected objects and fill gaps between them, either on the left, right, or in between lines and blocks. 923 944 // In order to get the repaint rect right, we have to examine left, middle, and right rects individually, since otherwise 924 945 // the union of those rects might remain the same even when changes have occurred. 925 typedef HashMap<RenderBlock*, std::unique_ptr<RenderBlockSelectionInfo>> SelectedBlockMap;926 SelectedBlockMap oldSelectedBlocks;927 SelectedBlockMap newSelectedBlocks;928 946 929 947 RenderObject* os = root.selectionStart(); … … 934 952 && os->selectionState() != SelectionNone) { 935 953 // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well. 936 oldSelect edObjects.set(os, std::make_unique<RenderSelectionInfo>(os, true));954 oldSelectionData.selectedObjects.set(os, std::make_unique<RenderSelectionInfo>(os, true)); 937 955 if (blockRepaintMode == RepaintNewXOROld) { 938 956 RenderBlock* cb = os->containingBlock(); 939 957 while (cb && !cb->isRenderView()) { 940 std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = oldSelect edBlocks.add(cb, nullptr).iterator->value;958 std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = oldSelectionData.selectedBlocks.add(cb, nullptr).iterator->value; 941 959 if (blockInfo) 942 960 break; … … 950 968 } 951 969 952 // Now clear the selection. 953 SelectedObjectMap::iterator oldObjectsEnd = oldSelectedObjects.end(); 954 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) 970 auto oldObjectsEnd = oldSelectionData.selectedObjects.end(); 971 for (auto i = oldSelectionData.selectedObjects.begin(); i != oldObjectsEnd; ++i) 955 972 i->key->setSelectionStateIfNeeded(SelectionNone); 956 957 // set selection start and end 958 root.setSelectionStart(start); 959 root.setSelectionStartPos(startPos); 960 root.setSelectionEnd(end); 961 root.setSelectionEndPos(endPos); 962 973 } 974 975 void RenderView::applySubtreeSelection(SelectionSubtreeRoot& root, RenderObject* start, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode, const OldSelectionData& oldSelectionData) 976 { 963 977 // Update the selection status of all objects between selectionStart and selectionEnd 964 978 if (start && start == end) … … 972 986 973 987 RenderObject* o = start; 974 stop = rendererAfterPosition(end, endPos);975 selectionIterator = SelectionIterator(o);988 RenderObject* stop = rendererAfterPosition(end, endPos); 989 SelectionIterator selectionIterator(o); 976 990 977 991 while (o && o != stop) { … … 986 1000 // Now that the selection state has been updated for the new objects, walk them again and 987 1001 // put them in the new objects list. 1002 SelectedObjectMap newSelectedObjects; 1003 SelectedBlockMap newSelectedBlocks; 988 1004 o = start; 989 1005 selectionIterator = SelectionIterator(o); … … 1020 1036 1021 1037 // Have any of the old selected objects changed compared to the new selection? 1022 for (SelectedObjectMap::iterator i = oldSelectedObjects.begin(); i != oldObjectsEnd; ++i) { 1023 RenderObject* obj = i->key; 1038 auto oldObjectsEnd = oldSelectionData.selectedObjects.end(); 1039 for (auto it = oldSelectionData.selectedObjects.begin(); it != oldObjectsEnd; ++it) { 1040 RenderObject* obj = it->key; 1024 1041 RenderSelectionInfo* newInfo = newSelectedObjects.get(obj); 1025 RenderSelectionInfo* oldInfo = i ->value.get();1042 RenderSelectionInfo* oldInfo = it->value.get(); 1026 1043 if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() 1027 || (root.selectionStart() == obj && oldS tartPos != root.selectionStartPos())1028 || (root.selectionEnd() == obj && old EndPos != root.selectionEndPos())) {1044 || (root.selectionStart() == obj && oldSelectionData.selectionStartPos != root.selectionStartPos()) 1045 || (root.selectionEnd() == obj && oldSelectionData.selectionEndPos != root.selectionEndPos())) { 1029 1046 oldInfo->repaint(); 1030 1047 if (newInfo) { … … 1036 1053 1037 1054 // Any new objects that remain were not found in the old objects dict, and so they need to be updated. 1038 SelectedObjectMap::iteratornewObjectsEnd = newSelectedObjects.end();1039 for ( SelectedObjectMap::iterator i = newSelectedObjects.begin(); i != newObjectsEnd; ++i)1040 i ->value->repaint();1055 auto newObjectsEnd = newSelectedObjects.end(); 1056 for (auto it = newSelectedObjects.begin(); it != newObjectsEnd; ++it) 1057 it->value->repaint(); 1041 1058 1042 1059 // Have any of the old blocks changed? 1043 SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();1044 for ( SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {1045 RenderBlock* block = i ->key;1060 auto oldBlocksEnd = oldSelectionData.selectedBlocks.end(); 1061 for (auto it = oldSelectionData.selectedBlocks.begin(); it != oldBlocksEnd; ++it) { 1062 RenderBlock* block = it->key; 1046 1063 RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block); 1047 RenderBlockSelectionInfo* oldInfo = i ->value.get();1064 RenderBlockSelectionInfo* oldInfo = it->value.get(); 1048 1065 if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) { 1049 1066 oldInfo->repaint(); … … 1056 1073 1057 1074 // Any new blocks that remain were not found in the old blocks dict, and so they need to be updated. 1058 SelectedBlockMap::iteratornewBlocksEnd = newSelectedBlocks.end();1059 for ( SelectedBlockMap::iterator i = newSelectedBlocks.begin(); i != newBlocksEnd; ++i)1060 i ->value->repaint();1075 auto newBlocksEnd = newSelectedBlocks.end(); 1076 for (auto it = newSelectedBlocks.begin(); it != newBlocksEnd; ++it) 1077 it->value->repaint(); 1061 1078 } 1062 1079 1063 1080 void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const 1064 1081 { 1065 startRenderer = m_ selectionStart;1066 startOffset = m_ selectionStartPos;1067 endRenderer = m_ selectionEnd;1068 endOffset = m_ selectionEndPos;1082 startRenderer = m_unsplitSelectionStart; 1083 startOffset = m_unsplitSelectionStartPos; 1084 endRenderer = m_unsplitSelectionEnd; 1085 endOffset = m_unsplitSelectionEndPos; 1069 1086 } 1070 1087 -
trunk/Source/WebCore/rendering/RenderView.h
r170774 r171218 90 90 void getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const; 91 91 void clearSelection(); 92 RenderObject* selection Start() const { return m_selectionStart; }93 RenderObject* selection End() const { return m_selectionEnd; }92 RenderObject* selectionUnsplitStart() const { return m_unsplitSelectionStart; } 93 RenderObject* selectionUnsplitEnd() const { return m_unsplitSelectionEnd; } 94 94 IntRect selectionBounds(bool clipToVisibleContent = true) const; 95 95 void repaintSelection() const; … … 305 305 306 306 void splitSelectionBetweenSubtrees(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode); 307 void setSubtreeSelection(SelectionSubtreeRoot&, RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode); 307 void clearSubtreeSelection(const SelectionSubtreeRoot&, SelectionRepaintMode, OldSelectionData&); 308 void updateSelectionForSubtrees(RenderSubtreesMap&, SelectionRepaintMode); 309 void applySubtreeSelection(SelectionSubtreeRoot&, RenderObject* start, RenderObject* end, int endPos, SelectionRepaintMode, const OldSelectionData&); 308 310 LayoutRect subtreeSelectionBounds(const SelectionSubtreeRoot&, bool clipToVisibleContent = true) const; 309 311 void repaintSubtreeSelection(const SelectionSubtreeRoot&) const; … … 312 314 FrameView& m_frameView; 313 315 314 RenderObject* m_ selectionStart;315 RenderObject* m_ selectionEnd;316 int m_ selectionStartPos;317 int m_ selectionEndPos;316 RenderObject* m_unsplitSelectionStart; 317 RenderObject* m_unsplitSelectionEnd; 318 int m_unsplitSelectionStartPos; 319 int m_unsplitSelectionEndPos; 318 320 319 321 uint64_t m_rendererCount; -
trunk/Source/WebCore/rendering/SelectionSubtreeRoot.cpp
r169273 r171218 46 46 } 47 47 48 SelectionSubtreeRoot::SelectionSubtreeRoot(RenderObject* selectionStart, int selectionStartPos, RenderObject* selectionEnd, int selectionEndPos) 49 : m_selectionStart(selectionStart) 50 , m_selectionStartPos(selectionStartPos) 51 , m_selectionEnd(selectionEnd) 52 , m_selectionEndPos(selectionEndPos) 53 { 54 } 55 48 56 void SelectionSubtreeRoot::adjustForVisibleSelection(Document& document) 49 57 { -
trunk/Source/WebCore/rendering/SelectionSubtreeRoot.h
r169273 r171218 32 32 33 33 #include "RenderObject.h" 34 #include "RenderSelectionInfo.h" 34 35 35 36 namespace WebCore { … … 39 40 class SelectionSubtreeRoot { 40 41 public: 42 43 typedef HashMap<RenderObject*, std::unique_ptr<RenderSelectionInfo>> SelectedObjectMap; 44 typedef HashMap<RenderBlock*, std::unique_ptr<RenderBlockSelectionInfo>> SelectedBlockMap; 45 typedef HashMap<SelectionSubtreeRoot*, SelectionSubtreeRoot> RenderSubtreesMap; 46 47 struct OldSelectionData { 48 OldSelectionData() 49 : selectionStartPos(-1) 50 , selectionEndPos(-1) 51 { 52 } 53 54 int selectionStartPos; 55 int selectionEndPos; 56 SelectedObjectMap selectedObjects; 57 SelectedBlockMap selectedBlocks; 58 }; 59 60 typedef HashMap<SelectionSubtreeRoot*, std::unique_ptr<OldSelectionData>> SubtreeOldSelectionDataMap; 41 61 42 62 SelectionSubtreeRoot(); 63 SelectionSubtreeRoot(RenderObject* selectionStart, int selectionStartPos, RenderObject* selectionEnd, int selectionEndPos); 43 64 44 65 RenderObject* selectionStart() const { return m_selectionStart; }
Note: See TracChangeset
for help on using the changeset viewer.