Closed Bug 362901 Opened 18 years ago Closed 17 years ago

[FIX]nsCSSFrameConstructor::HaveFirstLetterStyle broken in the presence of asynchronous restyles or batching

Categories

(Core :: Layout, defect, P1)

defect

Tracking

()

RESOLVED FIXED
mozilla1.9alpha4

People

(Reporter: dbaron, Assigned: bzbarsky)

References

()

Details

(Keywords: fixed1.8.0.15, fixed1.8.1.8, Whiteboard: [sg:critical?] One of the regression fixes is rev 3.828 of nsBlockFrame.cpp (no bug))

Attachments

(3 files, 2 obsolete files)

This is a bug on the second assertion described in bug 357531.  It could even also be related to the assertion we were seeing for a while going through the bloaturls on balsa -- maybe even still are.

nsCSSFrameConstructor::HaveFirstLetterStyle is quite broken in the presence of batching.  What seems to be happening in attachment 243039 [details] is the following:
 * the attachment, within one event:
   + changes the ID on the option such that the :first-letter style rule no longer applies, and
   + then removes the first child of the option

So when we get to nsCSSFrameConstructor::ContentRemoved, HaveFirstLetterStyle returns false because it uses ProbePseudoStyleContext based on the current style, not the style at the last time we processed restyle events.  So it concludes that there's no :first-letter frame to remove.

This means we end up with the non-first-letter frame still in the frame tree (we remove only the floating first letter frame), but pointing to content that's been removed from the content tree.

[ I think this problem is significantly worse due to asynchronous restyles, which I think are post-1.8 but not sure, but it may be present due to other batching mechanisms as well, or if we can trigger a failure of HaveFirstLetterStyle in other code, such as changing an attribute so that an element goes from having first letter style to having its first child with display:none. ]


The symptoms of this problem are the assertions loading attachment 243039 [details]:

WARNING: Content has no document.: file nsTextFrame.cpp, line 6143
WARNING: Reflow of frame failed in nsLineLayout: file nsLineLayout.cpp, line 890
WARNING: NS_ENSURE_TRUE(NS_SUCCEEDED(rv)) failed: file nsBlockFrame.cpp, line 3399
WARNING: NS_ENSURE_TRUE(NS_SUCCEEDED(rv)) failed: file nsBlockFrame.cpp, line 3230
WARNING: NS_ENSURE_TRUE(NS_SUCCEEDED(rv)) failed: file nsBlockFrame.cpp, line 1770
###!!! ASSERTION: reflow dirty lines failed: 'NS_SUCCEEDED(rv)', file nsBlockFrame.cpp, line 884
Whiteboard: [link to bug 357531 when opened]
Hmm...  So async restyles are in fact in 1.8.

Should we just switch the test to actually testing whether the first frame is a first-letter frame?  That might be faster than probing the style context anyway...

We'd half to walk the first-child chain, at the very least, and perhaps more if there are empty frames.
So I hate to ask this, but is there a free block-specific bit?  ;)
Blocks: 367650
Attached patch Proposed patch (obsolete) — Splinter Review
Turns out we already have a flag for this.  I went ahead and made it a little better maintained and started using it in favor of style context probing.
Assignee: nobody → bzbarsky
Status: NEW → ASSIGNED
Attachment #253848 - Flags: superreview?(dbaron)
Attachment #253848 - Flags: review?(dbaron)
Incidentally, that patch fixes bug 230611.

It's a patch on top of the one for bug 367650, so that will need to land first.

Clearing deps, since I just realized this is security-sensitive...
No longer blocks: 367650
Priority: -- → P1
Summary: nsCSSFrameConstructor::HaveFirstLetterStyle broken in the presence of asynchronous restyles or batching → [FIX]nsCSSFrameConstructor::HaveFirstLetterStyle broken in the presence of asynchronous restyles or batching
Whiteboard: [link to bug 357531 when opened] → [link to bug 357531, 230611, 367650 when opened]
Target Milestone: --- → mozilla1.9alpha
Whiteboard: [link to bug 357531, 230611, 367650 when opened] → [link to bug 357531, 230611, 367650, 372550 when opened]
Attached patch Minor tweak (obsolete) — Splinter Review
Have to add the flag even if there's no actual letter frame in case someone adds text later to an empty block or whatnot.
Attachment #253848 - Attachment is obsolete: true
Attachment #257272 - Flags: superreview?(dbaron)
Attachment #257272 - Flags: review?(dbaron)
Attachment #253848 - Flags: superreview?(dbaron)
Attachment #253848 - Flags: review?(dbaron)
Comment on attachment 257272 [details] [diff] [review]
Minor tweak

>+  NS_ASSERTION(aFrame != (nsIFrame*)0xdddddddd && aFrame->GetContent() != (nsIContent*)0xdddddddd,
>+               "oops");

If you really want this, it's ok, but I'd rather not put these everywhere.  Why here in particular?

>+#ifdef DEBUG
>+    // Verify that our NS_BLOCK_HAS_FIRST_LETTER_STYLE bit is correct,
>+    // as needed.
>     if (nsnull == GetPrevInFlow()) {
>       nsRefPtr<nsStyleContext> firstLetterStyle = GetFirstLetterStyle(presContext);
>+      NS_ASSERTION((firstLetterStyle != nsnull) ==
>+                   ((mState & NS_BLOCK_HAS_FIRST_LETTER_STYLE) != 0),
>+                   "State mismatch");
>     }
>+#endif

This could be just:

NS_ASSERTION(GetPrevInFlow() || 
             (nsRefPtr<nsStyleContext>(GetFirstLetterStyle(presContext)) != nsnull) ==
             ((mState & NS_BLOCK_HAS_FIRST_LETTER_STYLE) != 0),
             "NS_BLOCK_HAS_FIRST_LETTER_STYLE state out of sync");

although maybe GetPrevContinuation makes more sense.

>+#ifdef DEBUG
>+  {
>+    nsBlockFrame* block;
>+    NS_ASSERTION(NS_SUCCEEDED(aBlockFrame->QueryInterface(kBlockFrameCID,
>+                                                          (void**)&block)),

 && block
just to be sure.

(multiple occurrences)

>+                 "Not a block frame?");
>+  }
>+#endif

>+  aBlockFrame->RemoveStateBits(NS_BLOCK_HAS_FIRST_LETTER_STYLE);

Do the callers of RemoveLetterFrame really match the semantics of removing this bit?  I haven't checked...


Have you tested :first-letter on table cells?  Does it apply to the anonymous block inside?  Is this at least not regressing things?  (Should it work at all?)  Please file bugs if needed. :-)


r+sr=dbaron
Attachment #257272 - Flags: superreview?(dbaron)
Attachment #257272 - Flags: superreview+
Attachment #257272 - Flags: review?(dbaron)
Attachment #257272 - Flags: review+
> Why here in particular?

I was hitting it a lot with various mangled frame trees...  I didn't realize I'd left it in the diff; I'll take it out.

> This could be just:

Will do.

> although maybe GetPrevContinuation makes more sense.

Indeed, it does.  Will do.

> && block just to be sure.

Will do.

> Do the callers of RemoveLetterFrame really match the semantics of removing
> this

That's a good question.  Realistically, the only thing that the callers would need that bit for is knowing whether they need to remove letter frames, and they already know that...  I can probably take that line out.

> Have you tested :first-letter on table cells?

I haven't.  I'll do that.

bit?
"bit?"?
Ignore that part.  Shouldn't have been there.
> Have you tested :first-letter on table cells?

Now I have, and it works.  Which makes sense -- when constructing the frame we use the style context check, so call WrapFramesInFirstLetterFrame, so set the bit on the block inside the table cell.

I need to write a bunch of tests, including ones with <td> and <fieldset> and probably with some scrollable blocks.

Also note to self:  the only caller of nsBlockFrame::GetFirstLetterStyle is now debug code, so the method should be debug too.
Whiteboard: [link to bug 357531, 230611, 367650, 372550 when opened] → [link to depends on 357531, blocks 230611, depends on 367650, blocks 372550 when opened]
Attachment #257272 - Attachment is obsolete: true
Checked in on trunk.

David, do you think we should take this on branch?  We'd need to take the patch for bug 367650 as well, I think....
Status: ASSIGNED → RESOLVED
Closed: 17 years ago
Flags: in-testsuite+
Flags: blocking1.8.1.4?
Flags: blocking1.8.0.12?
Resolution: --- → FIXED
Target Milestone: mozilla1.9alpha1 → mozilla1.9alpha4
Flags: wanted1.8.1.x?
Flags: wanted1.8.0.x?
Will wait on the branch nominations until dbaron responds to comment 13
Flags: blocking1.8.1.4?
Flags: blocking1.8.0.12?
Whiteboard: [link to depends on 357531, blocks 230611, depends on 367650, blocks 372550 when opened] → [link to depends on 357531, blocks 230611, depends on 367650, blocks 372550, depends on 379383, depends on rev 3.828 of nsBlockFrame.cpp, depends on 379799 when opened]
Whiteboard: [link to depends on 357531, blocks 230611, depends on 367650, blocks 372550, depends on 379383, depends on rev 3.828 of nsBlockFrame.cpp, depends on 379799 when opened] → [sg:critical?] [link to depends on 357531, blocks 230611, depends on 367650, blocks 372550, depends on 379383, depends on rev 3.828 of nsBlockFrame.cpp, depends on 379799 when opened]
This bug fixed bug 372550, but can't add a dep because with the regression-tracking via deps that gives us a dep loop.  :(
Blocks: 230611
Depends on: 357531, 367650, 379383, 379799
Whiteboard: [sg:critical?] [link to depends on 357531, blocks 230611, depends on 367650, blocks 372550, depends on 379383, depends on rev 3.828 of nsBlockFrame.cpp, depends on 379799 when opened] → One of the regression fixes is rev 3.828 of nsBlockFrame.cpp (no bug)
Flags: wanted1.8.1.x?
Flags: wanted1.8.1.x+
Flags: wanted1.8.0.x?
Flags: wanted1.8.0.x+
Whiteboard: One of the regression fixes is rev 3.828 of nsBlockFrame.cpp (no bug) → [sg:critical?] One of the regression fixes is rev 3.828 of nsBlockFrame.cpp (no bug)
Flags: blocking1.8.1.5?
Flags: blocking1.8.0.13?
The idea of this patch isn't all that scary, and it's a relatively obscure feature, so I think we can take it on the branch if it's sufficiently tested.  I didn't look at bug 367650, though.
Need a 1.8 branch patch that incorporates the regression fixes, at least the one mentioned in the whiteboard that appears not to have gotten a bug.

Given the remaining unfixed 1.8.1.5 blockers we'll target this one for the next release for now, but will approve the above patch if it gets don't by the 1.8.1.5 code freeze (July 13).
Flags: blocking1.8.1.6+
Flags: blocking1.8.1.5?
Flags: blocking1.8.0.13?
Flags: blocking1.8.0.13+
This also depends a bit on the changes in bug: we only want to clean up generated content in inline and block frames.
Depends on: 257868
er, I meant in bug 257868.
Attached patch Branch patchSplinter Review
This includes the relevant part of bug 257868, all of bug 367650, this bug, bug 379383, bug 379799, and the notation in this bug's status whiteboard.

I've tested this on the testcases in all these bugs, and on the reftests I checked in for bug 367650.
Attachment #272139 - Flags: approval1.8.1.6?
Attachment #272139 - Flags: approval1.8.0.13?
Flags: blocking1.8.0.13+ → blocking1.8.0.14+
Attachment #272139 - Flags: approval1.8.0.13? → approval1.8.0.14?
Comment on attachment 272139 [details] [diff] [review]
Branch patch

nsBlockFrame.cpp
Attachment #272139 - Flags: approval1.8.1.7? → approval1.8.1.7+
> (From update of attachment 272139 [details] [diff] [review])
> nsBlockFrame.cpp

By which I mean "approved for 1.8.1.7, a=dveditz for release-drivers", of course
Fixed for 1.8.1.7
Keywords: fixed1.8.1.7
Group: security
Flags: blocking1.8.0.15+
Flags: blocking1.8.0.14-
Flags: blocking1.8.0.14+
a=asac for 1.8.0.15

(shipped by distro releases for some time)
Attachment #306267 - Flags: approval1.8.0.15+
Attachment #272139 - Flags: approval1.8.0.14?
please land on 1.8.0 branch.
Keywords: checkin-needed
MOZILLA_1_8_0_BRANCH:

Checking in layout/base/nsCSSFrameConstructor.cpp;
/cvsroot/mozilla/layout/base/nsCSSFrameConstructor.cpp,v  <--  nsCSSFrameConstructor.cpp
new revision: 1.1110.6.12.2.67; previous revision: 1.1110.6.12.2.66
done
Checking in layout/base/nsCSSFrameConstructor.h;
/cvsroot/mozilla/layout/base/nsCSSFrameConstructor.h,v  <--  nsCSSFrameConstructor.h
new revision: 1.187.6.3.2.8; previous revision: 1.187.6.3.2.7
done
Checking in layout/base/nsStyleChangeList.cpp;
/cvsroot/mozilla/layout/base/nsStyleChangeList.cpp,v  <--  nsStyleChangeList.cpp
new revision: 1.16.38.1; previous revision: 1.16
done
Checking in layout/generic/nsBlockFrame.cpp;
/cvsroot/mozilla/layout/generic/nsBlockFrame.cpp,v  <--  nsBlockFrame.cpp
new revision: 3.729.4.7.2.15; previous revision: 3.729.4.7.2.14
done
Checking in layout/generic/nsBlockFrame.h;
/cvsroot/mozilla/layout/generic/nsBlockFrame.h,v  <--  nsBlockFrame.h
new revision: 3.205.12.5; previous revision: 3.205.12.4
done
Checking in layout/generic/nsContainerFrame.cpp;
/cvsroot/mozilla/layout/generic/nsContainerFrame.cpp,v  <--  nsContainerFrame.cpp
new revision: 1.239.6.2.4.2; previous revision: 1.239.6.2.4.1
done
Checking in layout/generic/nsTextFrame.cpp;
/cvsroot/mozilla/layout/generic/Attic/nsTextFrame.cpp,v  <--  nsTextFrame.cpp
new revision: 1.513.4.6.2.6; previous revision: 1.513.4.6.2.5
done
Product: Core → Core Graveyard
Component: Layout: Misc Code → Layout
Product: Core Graveyard → Core
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: