Title: [93862] trunk/Source/WebCore
- Revision
- 93862
- Author
- [email protected]
- Date
- 2011-08-26 03:02:48 -0700 (Fri, 26 Aug 2011)
Log Message
2011-08-26 Nikolas Zimmermann <[email protected]>
[Qt] http/tests/misc/object-embedding-svg-delayed-size-negotiation-2.htm fails intermittently
https://bugs.webkit.org/show_bug.cgi?id=65969
Reviewed by Zoltan Herczeg.
Fix intrinsic size negotiation flakiness, most visible on the Qt port.
The http/tests/misc/object-embedding-svg-delayed-size-negotiation-2.htm testcase triggered
an assertion on a Qt debug build indicating that the HashSet updateLayoutAndStyleIfNeededRecursive()
operates on is mutated while its iterated, leading to an assertion/crash. Due the new forceLayoutParentViewIfNeeded()
logic it's no longer safe to directly use the children() HashSet in that method - we have to make a copy first.
The second part of the fix is to stop entering forceLayoutParentViewIfNeeded(), if the origin of that call
is forceLayoutParentViewIfNeeded() itself. Set m_inLayoutParentView to true before calling FrameView::layout()
on our parent frame view - this is only an optimization to avoid doing layout() twice.
The third part of the fix is to call updateWidgetPositions() on the parent FrameView, _before_ calling layout()
on the parent view itself, as the SVG document needs to report the correct intrinsic size (which can depend
on the host object/embed/iframe) when we're running RenderReplaced::layout() on the host renderer.
* page/FrameView.cpp:
(WebCore::FrameView::FrameView):
(WebCore::collectFrameViewChildren):
(WebCore::FrameView::forceLayoutParentViewIfNeeded):
(WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive):
* page/FrameView.h:
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (93861 => 93862)
--- trunk/Source/WebCore/ChangeLog 2011-08-26 09:56:17 UTC (rev 93861)
+++ trunk/Source/WebCore/ChangeLog 2011-08-26 10:02:48 UTC (rev 93862)
@@ -1,3 +1,32 @@
+2011-08-26 Nikolas Zimmermann <[email protected]>
+
+ [Qt] http/tests/misc/object-embedding-svg-delayed-size-negotiation-2.htm fails intermittently
+ https://bugs.webkit.org/show_bug.cgi?id=65969
+
+ Reviewed by Zoltan Herczeg.
+
+ Fix intrinsic size negotiation flakiness, most visible on the Qt port.
+
+ The http/tests/misc/object-embedding-svg-delayed-size-negotiation-2.htm testcase triggered
+ an assertion on a Qt debug build indicating that the HashSet updateLayoutAndStyleIfNeededRecursive()
+ operates on is mutated while its iterated, leading to an assertion/crash. Due the new forceLayoutParentViewIfNeeded()
+ logic it's no longer safe to directly use the children() HashSet in that method - we have to make a copy first.
+
+ The second part of the fix is to stop entering forceLayoutParentViewIfNeeded(), if the origin of that call
+ is forceLayoutParentViewIfNeeded() itself. Set m_inLayoutParentView to true before calling FrameView::layout()
+ on our parent frame view - this is only an optimization to avoid doing layout() twice.
+
+ The third part of the fix is to call updateWidgetPositions() on the parent FrameView, _before_ calling layout()
+ on the parent view itself, as the SVG document needs to report the correct intrinsic size (which can depend
+ on the host object/embed/iframe) when we're running RenderReplaced::layout() on the host renderer.
+
+ * page/FrameView.cpp:
+ (WebCore::FrameView::FrameView):
+ (WebCore::collectFrameViewChildren):
+ (WebCore::FrameView::forceLayoutParentViewIfNeeded):
+ (WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive):
+ * page/FrameView.h:
+
2011-08-26 Mikhail Naganov <[email protected]>
Web Inspector: [Chromium] Double clicking on numbers in Count & size columns doesn't toggle between values and percents in the Heap Snapshot.
Modified: trunk/Source/WebCore/page/FrameView.cpp (93861 => 93862)
--- trunk/Source/WebCore/page/FrameView.cpp 2011-08-26 09:56:17 UTC (rev 93861)
+++ trunk/Source/WebCore/page/FrameView.cpp 2011-08-26 10:02:48 UTC (rev 93862)
@@ -116,6 +116,9 @@
, m_fixedObjectCount(0)
, m_layoutTimer(this, &FrameView::layoutTimerFired)
, m_layoutRoot(0)
+#if ENABLE(SVG)
+ , m_inLayoutParentView(false)
+#endif
, m_hasPendingPostLayoutTasks(false)
, m_inSynchronousPostLayout(false)
, m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
@@ -836,9 +839,25 @@
return onlyDuringLayout && layoutPending() ? 0 : m_layoutRoot;
}
+static inline void collectFrameViewChildren(FrameView* frameView, Vector<RefPtr<FrameView> >& frameViews)
+{
+ const HashSet<RefPtr<Widget> >* viewChildren = frameView->children();
+ ASSERT(viewChildren);
+
+ const HashSet<RefPtr<Widget> >::iterator end = viewChildren->end();
+ for (HashSet<RefPtr<Widget> >::iterator current = viewChildren->begin(); current != end; ++current) {
+ Widget* widget = (*current).get();
+ if (widget->isFrameView())
+ frameViews.append(static_cast<FrameView*>(widget));
+ }
+}
+
inline void FrameView::forceLayoutParentViewIfNeeded()
{
#if ENABLE(SVG)
+ if (m_inLayoutParentView)
+ return;
+
RenderPart* ownerRenderer = m_frame->ownerRenderer();
if (!ownerRenderer || !ownerRenderer->frame())
return;
@@ -851,6 +870,8 @@
if (!svgRoot->needsSizeNegotiationWithHostDocument())
return;
+ m_inLayoutParentView = true;
+
// Clear needs-size-negotiation flag in RenderSVGRoot, so the next call to our
// layout() method won't fire the size negotiation logic again.
svgRoot->scheduledSizeNegotiationWithHostDocument();
@@ -859,10 +880,18 @@
// Mark the owner renderer as needing layout.
ownerRenderer->setNeedsLayoutAndPrefWidthsRecalc();
- // Synchronously enter layout.
+ // Immediately relayout the child widgets, which can now calculate the SVG documents
+ // intrinsic size, negotiating with the parent object/embed/iframe.
+ RenderView* rootView = ownerRenderer->frame()->contentRenderer();
+ ASSERT(rootView);
+ rootView->updateWidgetPositions();
+
+ // Synchronously enter layout, to layout the view containing the host object/embed/iframe.
FrameView* frameView = ownerRenderer->frame()->view();
ASSERT(frameView);
frameView->layout();
+
+ m_inLayoutParentView = false;
#endif
}
@@ -2720,14 +2749,16 @@
if (needsLayout())
layout();
- const HashSet<RefPtr<Widget> >* viewChildren = children();
- HashSet<RefPtr<Widget> >::const_iterator end = viewChildren->end();
- for (HashSet<RefPtr<Widget> >::const_iterator current = viewChildren->begin(); current != end; ++current) {
- Widget* widget = (*current).get();
- if (widget->isFrameView())
- static_cast<FrameView*>(widget)->updateLayoutAndStyleIfNeededRecursive();
- }
+ // Grab a copy of the children() set, as it may be mutated by the following updateLayoutAndStyleIfNeededRecursive
+ // calls, as they can potentially re-enter a layout of the parent frame view, which may add/remove scrollbars
+ // and thus mutates the children() set.
+ Vector<RefPtr<FrameView> > frameViews;
+ collectFrameViewChildren(this, frameViews);
+ const Vector<RefPtr<FrameView> >::iterator end = frameViews.end();
+ for (Vector<RefPtr<FrameView> >::iterator it = frameViews.begin(); it != end; ++it)
+ (*it)->updateLayoutAndStyleIfNeededRecursive();
+
// updateLayoutAndStyleIfNeededRecursive is called when we need to make sure style and layout are up-to-date before
// painting, so we need to flush out any deferred repaints too.
flushDeferredRepaints();
Modified: trunk/Source/WebCore/page/FrameView.h (93861 => 93862)
--- trunk/Source/WebCore/page/FrameView.h 2011-08-26 09:56:17 UTC (rev 93861)
+++ trunk/Source/WebCore/page/FrameView.h 2011-08-26 10:02:48 UTC (rev 93862)
@@ -400,6 +400,9 @@
bool m_layoutSchedulingEnabled;
bool m_inLayout;
+#if ENABLE(SVG)
+ bool m_inLayoutParentView;
+#endif
bool m_hasPendingPostLayoutTasks;
bool m_inSynchronousPostLayout;
int m_layoutCount;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes