Title: [189306] branches/safari-601-branch

Diff

Modified: branches/safari-601-branch/LayoutTests/ChangeLog (189305 => 189306)


--- branches/safari-601-branch/LayoutTests/ChangeLog	2015-09-03 22:53:51 UTC (rev 189305)
+++ branches/safari-601-branch/LayoutTests/ChangeLog	2015-09-03 23:03:59 UTC (rev 189306)
@@ -1,3 +1,24 @@
+2015-09-03  Babak Shafiei  <[email protected]>
+
+        Merge r186984.
+
+    2015-07-17  Zalan Bujtas  <[email protected]>
+
+            REGRESSION (r169105): Do not assign a renderer to multiple selection subtrees.
+            https://bugs.webkit.org/show_bug.cgi?id=147038
+            rdar://problem/21819351
+
+            Reviewed by David Kilzer.
+
+            A renderer should never be assigned to multiple selection subtrees. (Currently RenderObject maintains the last selection state.)
+            RenderView::applySubtreeSelection() loops from the start to the end of the selection to find renderers that are inside the selection.
+            However, in case of regions (when multiple selection roots are present) traversing the renderer tree by calling RenderObject::nextInPreOrder() could
+            end up going across selection roots.
+            This patch ensures that we assign renderers to a specific selection only when the current selection root and the renderer's selection root match.
+
+            * fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2-expected.txt: Added.
+            * fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2.html: Added.
+
 2015-08-28  Babak Shafiei  <[email protected]>
 
         Merge r189024.

Copied: branches/safari-601-branch/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2-expected.txt (from rev 186984, trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2-expected.txt) (0 => 189306)


--- branches/safari-601-branch/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2-expected.txt	                        (rev 0)
+++ branches/safari-601-branch/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2-expected.txt	2015-09-03 23:03:59 UTC (rev 189306)
@@ -0,0 +1,3 @@
+PASS if no assert or crash.
+
+foobar

Copied: branches/safari-601-branch/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2.html (from rev 186984, trunk/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2.html) (0 => 189306)


--- branches/safari-601-branch/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2.html	                        (rev 0)
+++ branches/safari-601-branch/LayoutTests/fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2.html	2015-09-03 23:03:59 UTC (rev 189306)
@@ -0,0 +1,23 @@
+<script>
+  if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.waitUntilDone();
+  }
+</script>
+<style>
+  div { -webkit-flow-into: content-flow; }
+  * { -webkit-flow-into: thread; }
+</style>
+<body _onload_="shuffle()"><p>PASS if no assert or crash.</p><div>content</div>foobar</body>
+<script>
+  document.execCommand("SelectAll");
+</script>
+<script>
+function shuffle() {
+  var element = document.getElementsByTagName("div")[0];
+  element.parentNode.removeChild(element);
+  document.body.offsetTop;
+  if (window.testRunner)
+    testRunner.notifyDone();
+}
+</script>

Modified: branches/safari-601-branch/Source/WebCore/ChangeLog (189305 => 189306)


--- branches/safari-601-branch/Source/WebCore/ChangeLog	2015-09-03 22:53:51 UTC (rev 189305)
+++ branches/safari-601-branch/Source/WebCore/ChangeLog	2015-09-03 23:03:59 UTC (rev 189306)
@@ -1,3 +1,29 @@
+2015-09-03  Babak Shafiei  <[email protected]>
+
+        Merge r186984.
+
+    2015-07-17  Zalan Bujtas  <[email protected]>
+
+            REGRESSION (r169105): Do not assign a renderer to multiple selection subtrees.
+            https://bugs.webkit.org/show_bug.cgi?id=147038
+            rdar://problem/21819351
+
+            Reviewed by David Kilzer.
+
+            A renderer should never be assigned to multiple selection subtrees. (Currently RenderObject maintains the last selection state.)
+            RenderView::applySubtreeSelection() loops from the start to the end of the selection to find renderers that are inside the selection.
+            However, in case of regions (when multiple selection roots are present) traversing the renderer tree by calling RenderObject::nextInPreOrder() could
+            end up going across selection roots.
+            This patch ensures that we assign renderers to a specific selection only when the current selection root and the renderer's selection root match.
+
+            Test: fast/regions/crash-when-renderer-is-in-multiple-selection-subtrees2.html
+
+            * rendering/RenderView.cpp:
+            (WebCore::SelectionIterator::SelectionIterator):
+            (WebCore::SelectionIterator::current):
+            (WebCore::SelectionIterator::checkForSpanner):
+            (WebCore::RenderView::applySubtreeSelection):
+
 2015-08-28  Babak Shafiei  <[email protected]>
 
         Merge r189024.

Modified: branches/safari-601-branch/Source/WebCore/rendering/RenderView.cpp (189305 => 189306)


--- branches/safari-601-branch/Source/WebCore/rendering/RenderView.cpp	2015-09-03 22:53:51 UTC (rev 189305)
+++ branches/safari-601-branch/Source/WebCore/rendering/RenderView.cpp	2015-09-03 23:03:59 UTC (rev 189306)
@@ -75,26 +75,14 @@
 };
 
 struct SelectionIterator {
-    RenderObject* m_current;
-    Vector<RenderMultiColumnSpannerPlaceholder*> m_spannerStack;
-    
-    SelectionIterator(RenderObject* o)
+    SelectionIterator(RenderObject* start)
+        : m_current(start)
     {
-        m_current = o;
         checkForSpanner();
     }
     
-    void checkForSpanner()
+    RenderObject* current() const
     {
-        if (!is<RenderMultiColumnSpannerPlaceholder>(m_current))
-            return;
-        auto& placeholder = downcast<RenderMultiColumnSpannerPlaceholder>(*m_current);
-        m_spannerStack.append(&placeholder);
-        m_current = placeholder.spanner();
-    }
-    
-    RenderObject* current()
-    {
         return m_current;
     }
     
@@ -111,6 +99,19 @@
         }
         return m_current;
     }
+
+private:
+    void checkForSpanner()
+    {
+        if (!is<RenderMultiColumnSpannerPlaceholder>(m_current))
+            return;
+        auto& placeholder = downcast<RenderMultiColumnSpannerPlaceholder>(*m_current);
+        m_spannerStack.append(&placeholder);
+        m_current = placeholder.spanner();
+    }
+
+    RenderObject* m_current { nullptr };
+    Vector<RenderMultiColumnSpannerPlaceholder*> m_spannerStack;
 };
 
 RenderView::RenderView(Document& document, Ref<RenderStyle>&& style)
@@ -1020,14 +1021,18 @@
             root.selectionData().selectionEnd()->setSelectionStateIfNeeded(SelectionEnd);
     }
 
-    RenderObject* o = root.selectionData().selectionStart();
-    RenderObject* stop = rendererAfterPosition(root.selectionData().selectionEnd(), root.selectionData().selectionEndPos());
-    SelectionIterator selectionIterator(o);
-    
-    while (o && o != stop) {
-        if (o != root.selectionData().selectionStart() && o != root.selectionData().selectionEnd() && o->canBeSelectionLeaf())
-            o->setSelectionStateIfNeeded(SelectionInside);
-        o = selectionIterator.next();
+    RenderObject* selectionStart = root.selectionData().selectionStart();
+    RenderObject* selectionEnd = rendererAfterPosition(root.selectionData().selectionEnd(), root.selectionData().selectionEndPos());
+    SelectionIterator selectionIterator(selectionStart);
+    for (RenderObject* currentRenderer = selectionStart; currentRenderer && currentRenderer != selectionEnd; currentRenderer = selectionIterator.next()) {
+        if (currentRenderer == root.selectionData().selectionStart() || currentRenderer == root.selectionData().selectionEnd())
+            continue;
+        if (!currentRenderer->canBeSelectionLeaf())
+            continue;
+        // FIXME: Move this logic to SelectionIterator::next()
+        if (&currentRenderer->selectionRoot() != &root)
+            continue;
+        currentRenderer->setSelectionStateIfNeeded(SelectionInside);
     }
 
     if (blockRepaintMode != RepaintNothing)
@@ -1037,36 +1042,33 @@
     // put them in the new objects list.
     SelectedObjectMap newSelectedObjects;
     SelectedBlockMap newSelectedBlocks;
-    o = root.selectionData().selectionStart();
-    selectionIterator = SelectionIterator(o);
-    while (o && o != stop) {
-        if (isValidObjectForNewSelection(root, *o)) {
-            std::unique_ptr<RenderSelectionInfo> selectionInfo = std::make_unique<RenderSelectionInfo>(*o, true);
+    selectionIterator = SelectionIterator(selectionStart);
+    for (RenderObject* currentRenderer = selectionStart; currentRenderer && currentRenderer != selectionEnd; currentRenderer = selectionIterator.next()) {
+        if (isValidObjectForNewSelection(root, *currentRenderer)) {
+            std::unique_ptr<RenderSelectionInfo> selectionInfo = std::make_unique<RenderSelectionInfo>(*currentRenderer, true);
 
 #if ENABLE(SERVICE_CONTROLS)
             for (auto& rect : selectionInfo->collectedSelectionRects())
                 m_selectionRectGatherer.addRect(selectionInfo->repaintContainer(), rect);
-            if (!o->isTextOrLineBreak())
+            if (!currentRenderer->isTextOrLineBreak())
                 m_selectionRectGatherer.setTextOnly(false);
 #endif
 
-            newSelectedObjects.set(o, WTF::move(selectionInfo));
+            newSelectedObjects.set(currentRenderer, WTF::move(selectionInfo));
 
-            RenderBlock* cb = o->containingBlock();
-            while (cb && !cb->isRenderView()) {
-                std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).iterator->value;
+            RenderBlock* containingBlock = currentRenderer->containingBlock();
+            while (containingBlock && !containingBlock->isRenderView()) {
+                std::unique_ptr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(containingBlock, nullptr).iterator->value;
                 if (blockInfo)
                     break;
-                blockInfo = std::make_unique<RenderBlockSelectionInfo>(*cb);
-                cb = cb->containingBlock();
+                blockInfo = std::make_unique<RenderBlockSelectionInfo>(*containingBlock);
+                containingBlock = containingBlock->containingBlock();
 
 #if ENABLE(SERVICE_CONTROLS)
                 m_selectionRectGatherer.addGapRects(blockInfo->repaintContainer(), blockInfo->rects());
 #endif
             }
         }
-
-        o = selectionIterator.next();
     }
 
     if (blockRepaintMode == RepaintNothing)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to