Changeset 45710 in webkit


Ignore:
Timestamp:
Jul 10, 2009 9:54:14 AM (15 years ago)
Author:
mitz@apple.com
Message:

WebCore:

Reviewed by Simon Fraser.

Test: fast/loader/goto-anchor-infinite-layout.html

  • loader/FrameLoader.cpp: (WebCore::FrameLoader::gotoAnchor): Moved the code to update layout, find the renderer to scroll to, and scroll from here to methods on FrameView, and replaced it with a call to FrameView::maintainScrollPositionAtAnchor(). (WebCore::FrameLoader::completed): Call maintainScrollPositionAtAnchor() instead of setLockedToAnchor().
  • page/FrameView.cpp: (WebCore::FrameView::FrameView): Removed initialization of m_lockedToAnchor. (WebCore::FrameView::reset): Reset m_maintainScrollPositionAnchor instead of m_lockedToAnchor. (WebCore::FrameView::layout): Removed the code related to scrolling to the anchor from here, because scrolling can trigger events which invalidate the layout, and as such, belongs with the post-layout tasks. (WebCore::FrameView::maintainScrollPositionAtAnchor): Added. When called with a node scrolls the view to the top of that node and maintains it scrolled to the top of the node during subsequent layouts, until this function is called with 0 or other things trigger scrolling. (WebCore::FrameView::scrollRectIntoViewRecursively): Reset m_maintainScrollPositionAnchor. (WebCore::FrameView::setScrollPosition): Ditto. (WebCore::FrameView::scrollToAnchor): Added. Scrolls to the top of m_maintainScrollPositionAnchor, if it is set. (WebCore::FrameView::performPostLayoutTasks): Call scrollToAnchor(). (WebCore::FrameView::setWasScrolledByUser): Reset m_maintainScrollPositionAnchor.
  • page/FrameView.h: Removed lockedToAnchor(), setLockedToAnchor(), and m_lockedToAnchor. Added maintainScrollPositionAtAnchor() and m_maintainScrollPositionAnchor.

LayoutTests:

Reviewed by Simon Fraser.

  • fast/loader/goto-anchor-infinite-layout-expected.txt: Added.
  • fast/loader/goto-anchor-infinite-layout.html: Added.
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r45709 r45710  
     12009-07-10  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Simon Fraser.
     4
     5        - test for https://bugs.webkit.org/show_bug.cgi?id=27137
     6          <rdar://problem/7043124> REGRESSION (r44311): Reproducible crash due
     7          to infinite recursion into FrameLoader::gotoAnchor() ->
     8          FrameView::layout()
     9
     10        * fast/loader/goto-anchor-infinite-layout-expected.txt: Added.
     11        * fast/loader/goto-anchor-infinite-layout.html: Added.
     12
    1132009-07-09  Simon Hausmann  <hausmann@webkit.org>
    214
  • trunk/WebCore/ChangeLog

    r45707 r45710  
     12009-07-10  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Simon Fraser.
     4
     5        - fix https://bugs.webkit.org/show_bug.cgi?id=27137
     6          <rdar://problem/7043124> REGRESSION (r44311): Reproducible crash due
     7          to infinite recursion into FrameLoader::gotoAnchor() ->
     8          FrameView::layout()
     9
     10        Test: fast/loader/goto-anchor-infinite-layout.html
     11
     12        * loader/FrameLoader.cpp:
     13        (WebCore::FrameLoader::gotoAnchor): Moved the code to update layout,
     14        find the renderer to scroll to, and scroll from here to methods on
     15        FrameView, and replaced it with a call to
     16        FrameView::maintainScrollPositionAtAnchor().
     17        (WebCore::FrameLoader::completed): Call maintainScrollPositionAtAnchor()
     18        instead of setLockedToAnchor().
     19
     20        * page/FrameView.cpp:
     21        (WebCore::FrameView::FrameView): Removed initialization of
     22        m_lockedToAnchor.
     23        (WebCore::FrameView::reset): Reset m_maintainScrollPositionAnchor instead
     24        of m_lockedToAnchor.
     25        (WebCore::FrameView::layout): Removed the code related to scrolling to
     26        the anchor from here, because scrolling can trigger events which
     27        invalidate the layout, and as such, belongs with the post-layout tasks.
     28        (WebCore::FrameView::maintainScrollPositionAtAnchor): Added. When called
     29        with a node scrolls the view to the top of that node and maintains it
     30        scrolled to the top of the node during subsequent layouts, until
     31        this function is called with 0 or other things trigger scrolling.
     32        (WebCore::FrameView::scrollRectIntoViewRecursively): Reset
     33        m_maintainScrollPositionAnchor.
     34        (WebCore::FrameView::setScrollPosition): Ditto.
     35        (WebCore::FrameView::scrollToAnchor): Added. Scrolls to the top of
     36        m_maintainScrollPositionAnchor, if it is set.
     37        (WebCore::FrameView::performPostLayoutTasks): Call scrollToAnchor().
     38        (WebCore::FrameView::setWasScrolledByUser): Reset
     39        m_maintainScrollPositionAnchor.
     40
     41        * page/FrameView.h: Removed lockedToAnchor(), setLockedToAnchor(),
     42        and m_lockedToAnchor. Added maintainScrollPositionAtAnchor() and
     43        m_maintainScrollPositionAnchor.
     44
    1452009-07-04  Sriram Yadavalli  <sriram.yadavalli@nokia.com>
    246
  • trunk/WebCore/loader/FrameLoader.cpp

    r45679 r45710  
    15901590        return false;
    15911591
    1592     // We need to update the layout before scrolling, otherwise we could
    1593     // really mess things up if an anchor scroll comes at a bad moment.
    1594     m_frame->document()->updateStyleIfNeeded();
    1595     // Only do a layout if changes have occurred that make it necessary.
    1596     if (m_frame->view() && m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
    1597         m_frame->view()->layout();
    1598  
    1599     // Scroll nested layers and frames to reveal the anchor.
    1600     // Align to the top and to the closest side (this matches other browsers).
    1601     RenderObject* renderer;
    1602     IntRect rect;
    1603     if (!anchorNode)
    1604         renderer = m_frame->document()->renderer(); // top of document
    1605     else {
    1606         renderer = anchorNode->renderer();
    1607         rect = anchorNode->getRect();
    1608     }
    1609     if (renderer) {
    1610         renderer->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
    1611         if (m_frame->view())
    1612             m_frame->view()->setLockedToAnchor(true);
    1613     }
     1592    if (FrameView* view = m_frame->view())
     1593        view->maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
    16141594
    16151595    return true;
     
    21152095        parent->loader()->checkCompleted();
    21162096    if (m_frame->view())
    2117         m_frame->view()->setLockedToAnchor(false);
     2097        m_frame->view()->maintainScrollPositionAtAnchor(0);
    21182098}
    21192099
  • trunk/WebCore/page/FrameView.cpp

    r45679 r45710  
    112112    , m_deferSetNeedsLayouts(0)
    113113    , m_setNeedsLayoutWasDeferred(false)
    114     , m_lockedToAnchor(false)
    115114{
    116115    init();
     
    186185    m_isVisuallyNonEmpty = false;
    187186    m_firstVisuallyNonEmptyLayoutCallbackPending = true;
    188     m_lockedToAnchor = false;
     187    m_maintainScrollPositionAnchor = 0;
    189188}
    190189
     
    667666    }
    668667
    669     if (lockedToAnchor())
    670         m_frame->loader()->gotoAnchor();
    671 
    672668    m_nestedLayoutCount--;
    673669}
     
    752748}
    753749
     750void FrameView::maintainScrollPositionAtAnchor(Node* anchorNode)
     751{
     752    m_maintainScrollPositionAnchor = anchorNode;
     753    if (!m_maintainScrollPositionAnchor)
     754        return;
     755
     756    // We need to update the layout before scrolling, otherwise we could
     757    // really mess things up if an anchor scroll comes at a bad moment.
     758    m_frame->document()->updateStyleIfNeeded();
     759    // Only do a layout if changes have occurred that make it necessary.
     760    if (m_frame->contentRenderer() && m_frame->contentRenderer()->needsLayout())
     761        layout();
     762    else
     763        scrollToAnchor();
     764}
     765
    754766void FrameView::scrollRectIntoViewRecursively(const IntRect& r)
    755767{
    756768    bool wasInProgrammaticScroll = m_inProgrammaticScroll;
    757769    m_inProgrammaticScroll = true;
    758     setLockedToAnchor(false);
     770    m_maintainScrollPositionAnchor = 0;
    759771    ScrollView::scrollRectIntoViewRecursively(r);
    760772    m_inProgrammaticScroll = wasInProgrammaticScroll;
     
    765777    bool wasInProgrammaticScroll = m_inProgrammaticScroll;
    766778    m_inProgrammaticScroll = true;
    767     setLockedToAnchor(false);
     779    m_maintainScrollPositionAnchor = 0;
    768780    ScrollView::setScrollPosition(scrollPoint);
    769781    m_inProgrammaticScroll = wasInProgrammaticScroll;
     
    11191131}
    11201132
     1133void FrameView::scrollToAnchor()
     1134{
     1135    RefPtr<Node> anchorNode = m_maintainScrollPositionAnchor;
     1136    if (!anchorNode)
     1137        return;
     1138
     1139    if (!anchorNode->renderer())
     1140        return;
     1141
     1142    IntRect rect;
     1143    if (anchorNode != m_frame->document())
     1144        rect = anchorNode->getRect();
     1145
     1146    // Scroll nested layers and frames to reveal the anchor.
     1147    // Align to the top and to the closest side (this matches other browsers).
     1148    anchorNode->renderer()->enclosingLayer()->scrollRectToVisible(rect, true, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignTopAlways);
     1149
     1150    // scrollRectToVisible can call into scrollRectIntoViewRecursively(), which resets m_maintainScrollPositionAnchor.
     1151    m_maintainScrollPositionAnchor = anchorNode;
     1152}
     1153
    11211154bool FrameView::updateWidgets()
    11221155{
     
    11621195            break;
    11631196    }
    1164    
     1197
     1198    scrollToAnchor();
     1199
    11651200    resumeScheduledEvents();
    11661201
     
    13521387    if (m_inProgrammaticScroll)
    13531388        return;
    1354     setLockedToAnchor(false);
     1389    m_maintainScrollPositionAnchor = 0;
    13551390    m_wasScrolledByUser = wasScrolledByUser;
    13561391}
  • trunk/WebCore/page/FrameView.h

    r45679 r45710  
    180180    void adjustPageHeight(float* newBottom, float oldTop, float oldBottom, float bottomLimit);
    181181
    182     bool lockedToAnchor() { return m_lockedToAnchor; }
    183     void setLockedToAnchor(bool lockedToAnchor) { m_lockedToAnchor = lockedToAnchor; }
     182    void maintainScrollPositionAtAnchor(Node*);
    184183
    185184    // Methods to convert points and rects between the coordinate space of the renderer, and this view.
     
    234233
    235234    bool updateWidgets();
     235    void scrollToAnchor();
    236236   
    237237    static double sCurrentPaintTimeStamp; // used for detecting decoded resource thrash in the cache
     
    303303    bool m_firstVisuallyNonEmptyLayoutCallbackPending;
    304304
    305     bool m_lockedToAnchor;
     305    RefPtr<Node> m_maintainScrollPositionAnchor;
    306306};
    307307
Note: See TracChangeset for help on using the changeset viewer.