Closed Bug 562955 Opened 14 years ago Closed 14 years ago

opt test mochitests-4/5: /tests/layout/base/tests/test_bug458898.html | innerHeight: 0 >= 200 ?

Categories

(Core :: Layout, defect)

All
Windows 7
defect
Not set
major

Tracking

()

RESOLVED FIXED
mozilla2.0b7
Tracking Status
blocking2.0 --- betaN+
status1.9.2 --- ?

People

(Reporter: anodelman, Assigned: jimm)

References

Details

Attachments

(3 files, 5 obsolete files)

From unit tests run on talos win7 machines.

562 ERROR TEST-UNEXPECTED-FAIL | /tests/layout/base/tests/test_bug458898.html | innerHeight: 0 >= 200 ?
That sounds bad.  Is the window actually opening as the wrong size?
I wonder if this is related to bug 558479 that I've been seeing for some time on trunk/win7 now. Can you get a screenshot of the window/desktop when this happens?
Does this test fail every time on Win7, or just some of the time?
This is consistently orange on windows 7 for unit test on talos currently being staged.
dbaron: can you take a look?
I think this is most likely a windows widget code bug, and that jimm or robarnold would be the best people to look into it.
I get this reproducibly on Windows 7 in a JM build. docShellWin->GetSize() returns (117, 0), so it seems this is the same bug.
This permanently fails on 64-bit win7, too. Can someone take a look at this, we don't have other 64-bit test platforms on Windows.
Blocks: 564257
Severity: normal → major
Component: Layout → Widget: Win32
QA Contact: layout → win32
We are now running the Windows 7 unit tests on production but hidden.

This is one of the 4 test suites left to greenize on Windows 7 and we want to
make this green as soon as it is possible to help us move load from the Win2k3
machines to the Win7 machines (it will really help us). Any help that you can
give us will be really appreciate it since this block us to roll this goal out.

You can find logs for it under:
http://tinderbox.mozilla.org/showbuilds.cgi?tree=Firefox&noignore=1
as:
* Rev3 WINNT 6.1 mozilla-central opt test mochitests-4/5
This bug is still valid and there is no assigned owner.
This blocks us from switching from running unit tests on the builders to the minis and therefore improve wait times.
blocking2.0: ? → final+
Assignee: nobody → jmuizelaar
You can also find the current logs by going to:
http://tests.themasta.com/tinderboxpushlog/?noignore=1
and looking for the "Mo (4)" build on the Win7 line.
Assignee: jmuizelaar → jmathies
Hi Jim, what is the status update in here?
Anyone else that could help you with this?
(In reply to comment #13)
> Hi Jim, what is the status update in here?
> Anyone else that could help you with this?

Been busy and haven't had a chance to look at this. I'm headed into pto, I'll be back 8/18. I might be able to get to this after that, but I can't promise anything.
blocking2.0: final+ → betaN+
I disabled this test.

http://hg.mozilla.org/tracemonkey/rev/ad7f95eb5fd5

This will get merged to m-c soon. Tracemonkey shows the few remaining Windows 7 failures, so I'm landing them there to make sure I've correctly disabled the tests.
(In reply to comment #15)
> I disabled this test.
> 
> http://hg.mozilla.org/tracemonkey/rev/ad7f95eb5fd5
> 
> This will get merged to m-c soon. Tracemonkey shows the few remaining Windows 7
> failures, so I'm landing them there to make sure I've correctly disabled the
> tests.

Ping - any ETA? (Sorry for the pester, but we're eager to disable those tests-on-builders, and improve wait times.)
Merged, and Win7 Mo4 unhidden on mozilla-central and e10s.
Hmm, sizeToContent appears broken. We're not getting the right size values. This appears broken on all windows platforms, not just win7.
No longer blocks: 564257
Attached file stand alone test
Attached patch fix (obsolete) — Splinter Review
waiting on a try run to confirm this fix.
So this bug is triggered by dumb luck. In nsHTMLReflowState's InitResizeFlags, we set a horizontal reflow flag based on a set of checks:

362 mFlags.mHResize = !(frame->GetStateBits() & NS_FRAME_IS_DIRTY) &&
363 frame->GetSize().width !=
364 mComputedWidth + mComputedBorderPadding.LeftRight(); 

Coincidentally the default window width on Win7 (132 pixels) results in an inner frame width of 100px, which is the same width this test sets. So mFlags.mHResize ends up being false.

http://hg.mozilla.org/mozilla-central/annotate/f5603541696d/layout/generic/nsHTMLReflowState.cpp#l360

In ViewportFrame's Reflow, we use the result of this via ShouldReflowAllKids() to decide if we should reflow. ShouldReflowAllKids returns false, so the visible area of the window never gets updated, and that in turn causes SizeToContent to resize the window to the default (which it already is).

This bug can be triggered on XP, you just have to adjust the width in the test down 1px (99px in the test). I suppose you could do the same on other platforms. This is also reproducible in 3.6.

I'm unsure of how to fix this. The width check appears to be unreliable. It also seems odd that NS_FRAME_IS_DIRTY isn't set on the frame. I'm still trying to sort that out.

(Moving this over to layout since it's not a widget bug.)
Component: Widget: Win32 → Layout
QA Contact: win32 → layout
status1.9.2: --- → ?
> It also seems odd that NS_FRAME_IS_DIRTY isn't set on the frame.

Indeed.  For the first reflow it should be set... and for later ones we should have already reflowed at GetSize().width and hence not need any updating if the width hasn't changed.

And in fact, you're saying that frame->GetSize().width is nonzero, right?  So we have already been laid out at this width once.  What's the issue?

Or maybe more precisely.... how is the stuff that you think should be reflowed but isn't related to |frame| in the above code?  Is |frame| above a viewport frame?
(In reply to comment #22)
> > It also seems odd that NS_FRAME_IS_DIRTY isn't set on the frame.
> 
> Indeed.  For the first reflow it should be set... and for later ones we should
> have already reflowed at GetSize().width and hence not need any updating if the
> width hasn't changed.
> 
> And in fact, you're saying that frame->GetSize().width is nonzero, right?  So
> we have already been laid out at this width once.  What's the issue?
> 
> Or maybe more precisely.... how is the stuff that you think should be reflowed
> but isn't related to |frame| in the above code?  Is |frame| above a viewport
> frame?


The value for frame->GetSize().width apparently propagates up from the widget, it's the default width of the window. mFlags.mHResize ends up being false, which causes mFlags.mVResize to be false, and this prevents us from calculating the proper height of the content. That in turn messes up SizeToContent which pulls dims from pres context's GetVisibleArea(). 

I got side tracked today but will be looking at this more tomorrow.
> The value for frame->GetSize().width apparently propagates up from the widget,
> it's the default width of the window.

Sure, but the only way it can "propagate" is via reflow, right?  That's where we set frame sizes.  Or is someone doing a guerilla SetSize() or SetRect() on a frame?

So is the issue here that we reflow the document once at the default size, then try to SizeToContent?  We should be guaranteeing that SizeToContent either sets both resize flags on the root or more simply just does a dirty reflow, imo.  But why do we have a reflow before the SizeToContent one?  Is that a bug or just life?
(In reply to comment #24)
> > The value for frame->GetSize().width apparently propagates up from the widget,
> > it's the default width of the window.
> 
> Sure, but the only way it can "propagate" is via reflow, right?  That's where
> we set frame sizes.  Or is someone doing a guerilla SetSize() or SetRect() on a
> frame?
> 
> So is the issue here that we reflow the document once at the default size, then
> try to SizeToContent?

No doesn't look like it. This seems to be happening on the first reflow which is triggered by nsDocumentViewer's SizeToContent calling ResizeReflow.

In DoReflow, we setup reflowState, which gets passed to target->Reflow. That in turn returns a desiredSize. If mComputedWidth matches up to the frame width (which is already set to the default window width), desiredSize.height is set to zero. At the end of DoReflow, we set the frame height to the desired height (0). Then in the tail end of ResizeReflow, we set the visible area height to the root frame height (also 0).

> We should be guaranteeing that SizeToContent either sets
> both resize flags on the root or more simply just does a dirty reflow, imo.

Getting the reflowState flags set right from SizeToContent looks tricky. These two are abstracted from each other by a number of generic calls. However a call in nsDocumentViewer's SizeToContent to preshell->StyleChangeReflow() prior to the presshell->ResizeReflow() fixes this.

Would that be an acceptable solution? (I don't want to totally bork something else or kill performance somehow.
> (which is already set to the default window width)

Why did that happen?  Who set it?

I'd need to think a bit before I can answer the questions at the end there.
(In reply to comment #26)
> > (which is already set to the default window width)
> 
> Why did that happen?  Who set it?
> 
> I'd need to think a bit before I can answer the questions at the end there.

It gets passed up when the window is created:

> xul.dll!nsDocShell::SetPositionAndSize
xul.dll!nsDocShell::InitWindow
xul.dll!nsWebShellWindow::Initialize
xul.dll!nsAppShellService::JustCreateTopWindow
xul.dll!nsAppShellService::CreateTopLevelWindow

That sets mBounds, which is then used in DocumentViewerImpl's InitPresentationStuff to set the initial visible area on the pres context.
Attached patch patch (obsolete) — Splinter Review
This targets the specific case we're interested in without effecting any other situation.
Attachment #476872 - Attachment is obsolete: true
Attachment #478366 - Flags: feedback?(bzbarsky)
> That sets mBounds, which is then used in DocumentViewerImpl's
> InitPresentationStuff to set the initial visible area on the pres context.

Yes, but what sets that size on the _frame_?
Attached file stacks and code (obsolete) —
(In reply to comment #29)
> > That sets mBounds, which is then used in DocumentViewerImpl's
> > InitPresentationStuff to set the initial visible area on the pres context.
> 
> Yes, but what sets that size on the _frame_?

Ok, this value is initialized in PresShell::DoReflow on the initial refresh timer.

Attached stacks show how it gets sets.
Attached file stacks and code
with the right second stack
Attachment #478401 - Attachment is obsolete: true
OK, so a reflow before the SizeToContent attempt, yes.  I believe that!
So another option is to change PresShell::DoReflow such that if |root == rootFrame| and size.height is unconstrained we just force the mVResize flag to true.  That should only happen in SizeToContent cases, I believe, and will avoid the extra work that dirty reflows entail.   Run that idea by dbaron, though, just to make sure I'm not on crack?
Attached patch mVResize patch (obsolete) — Splinter Review
(In reply to comment #33)
> So another option is to change PresShell::DoReflow such that if |root ==
> rootFrame| and size.height is unconstrained we just force the mVResize flag to
> true.  That should only happen in SizeToContent cases, I believe, and will
> avoid the extra work that dirty reflows entail.   Run that idea by dbaron,
> though, just to make sure I'm not on crack?

This seems to hit the case we're trying to catch. This is within a block where |mComputedHeight == NS_AUTOHEIGHT|, and |parentReflowState == nsnull| on root reflows.
Attachment #478659 - Flags: feedback?(bzbarsky)
Attachment #478366 - Flags: feedback?(bzbarsky)
Comment on attachment 478659 [details] [diff] [review]
mVResize patch

I'd really rather do that in DoReflow, as I said.  parentReflowState can be null for non-root-frame reflows (specifically, for any reflow root), so this patch isn't right.  But in DoReflow we know whether we're really reflowing the root.
Attachment #478659 - Flags: feedback?(bzbarsky) → feedback-
Attached patch DoReflow patch (obsolete) — Splinter Review
Seems a little odd accessing these flags from outside InitResizeFlags. I could also hand down a flag in a new constructor if that seems more appropriate.
Attachment #478674 - Flags: feedback?(bzbarsky)
Attachment #478659 - Attachment is obsolete: true
(In reply to comment #33)
> So another option is to change PresShell::DoReflow such that if |root ==
> rootFrame| and size.height is unconstrained we just force the mVResize flag to
> true.  That should only happen in SizeToContent cases, I believe, and will
> avoid the extra work that dirty reflows entail.   Run that idea by dbaron,
> though, just to make sure I'm not on crack?

The basic idea sounds good.

But I'm wondering if we need to force mVResize to true again on the way back (i.e., when switching from unconstrained height to fixed height) as well, when we reflow a second time with the size from the first time.  Aren't there percentage heights that will behave differently there?
(In reply to comment #37)
> (In reply to comment #33)
> > So another option is to change PresShell::DoReflow such that if |root ==
> > rootFrame| and size.height is unconstrained we just force the mVResize flag to
> > true.  That should only happen in SizeToContent cases, I believe, and will
> > avoid the extra work that dirty reflows entail.   Run that idea by dbaron,
> > though, just to make sure I'm not on crack?
> 
> The basic idea sounds good.
> 
> But I'm wondering if we need to force mVResize to true again on the way back
> (i.e., when switching from unconstrained height to fixed height) as well, when
> we reflow a second time with the size from the first time.  Aren't there
> percentage heights that will behave differently there?

A percentage height in this test case has no effect on sizeToContent. I'm not sure how it could, layout doesn't have a value to calculate a percentage of.
> Aren't there percentage heights that will behave differently there?

Hmm.... In quirks mode there almost certainly are.  Not sure about standards mode.

On the followup reflow, are we doing a ResizeReflow for which the old size is unconstrained and the new size is whatever the size was computed to be?
(In reply to comment #39)
> > Aren't there percentage heights that will behave differently there?
> 
> Hmm.... In quirks mode there almost certainly are.  Not sure about standards
> mode.
> 
> On the followup reflow, are we doing a ResizeReflow for which the old size is
> unconstrained and the new size is whatever the size was computed to be?

Well, on the followup, we don't even necessarily *do* a reflow if it doesn't involve resizing the widget, which seems rather bad.  (See nsXULWindow::SizeShellTo, called from DocumentViewerImpl::SizeToContent.)  I guess I won't worry about that bit right now.

If it weren't expensive in quirks mode, I'd say we should just set mVResize to true on the root element all the time.  (In quirks mode, it'll propagate to all non-fixed-height elements.)

As is, though, I think we should probably add a boolean to the pres shell (defaulting to false) called something like mLastRootReflowUnconstrainedHeight, and set and use it appropriately in this code (so we set mVResize if either the previous or the current reflow was unconstrained height).
Attached patch patchSplinter Review
jimm asked if I could write the patch I was thinking of; here it is.

I'll send this to try server shortly.
Attachment #478366 - Attachment is obsolete: true
Attachment #478674 - Attachment is obsolete: true
Attachment #479159 - Flags: review?(bzbarsky)
Attachment #478674 - Flags: feedback?(bzbarsky)
Comment on attachment 479159 [details] [diff] [review]
patch

r=me
Attachment #479159 - Flags: review?(bzbarsky) → review+
Landed: http://hg.mozilla.org/mozilla-central/rev/769faecf13a9

Thanks for all the work on this, Jim, and sorry for blaming the widget code on this one.  I clearly got that wrong.
Status: NEW → RESOLVED
Closed: 14 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla2.0b8
(In reply to comment #43)
> Landed: http://hg.mozilla.org/mozilla-central/rev/769faecf13a9
> 
> Thanks for all the work on this, Jim, and sorry for blaming the widget code on
> this one.  I clearly got that wrong.

NP, thanks for putting together the final patch. (..and thanks for the help and patience bz!)
Target Milestone: mozilla2.0b8 → mozilla2.0b7
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: