The attached file causes Safari to hang (tested on r20849, but same result on release version) for about a minute, on a quad MacPro. Scrolling is also jerky after loading. In Firefox, loading is instant, and scrolling is fine.
Created attachment 14012 [details]
html file demonstrating problem
Forgot to add - when file is open, memory increases by several hundred megabytes. In contrast, Firefox uses less than 100Mb.
This page is extremely malformed and is nesting <span>s to an insane level. Basically the spans not being closed properly is causing us to nest all the spans inside one another. I'm not sure how Firefox is avoiding this... maybe by having a maximum allowed document tree depth.
My testing shows that IE nests infinitely (and hangs), while Firefox nests up to 201 (where <html> counts as 0 and <body> counts as 1), parsing all subsequent nested tags as siblings.
Created attachment 14029 [details]
Test for how deeply a browser will nest tags, and the resulting DOM.
Created attachment 14030 [details]
Fixed test description.
"IE" above means IE 6 and IE 7.
Firefox does not restrict nesting in XML documents, but in HTML documents it restricts nesting in both quirks and standards modes.
That makes sense, since these nesting situations are always malformed, and you can't malform XML.
Opera cuts you off at nesting depth 500 and throws away any further nested elements! (Then it hangs, anyway.)
According to Mozilla's bugzilla (see 377056, 256180, and 58917 for starters), this kind of deep nesting often occurs as a result of broken HTML editors or PHP/PERL scripts.
Other potential causes for this problem include a developer who serves XHTML as text/html, and a developer who simply doesn't understand that self-closing is an XML-only feature, and uses self-closing notation in plain HTML. In such cases, any nominally self-closed tags, like <div/>, will actually nest.
The max nesting depth of attachment 14012 [details] is 4061 tags.
If we define a hang as a pause > 10 seconds, then, on my MacBook Pro, depending on whether the nesting is a span, a div, or a span/div pair, WebKit can handle a nesting depth of 14,000, 9,000, or 1250, respectively.
Those numbers also depend on the content of the tags and their style. For example, attachment 14012 [details] is only SPAN elements, but each is styled and contains substantial content. On my MacBook Pro, WebKit can only handle a depth of about 2,000.
IE 6 and IE 7 honor the nesting in attachment 14012 [details] without any noticeable performance problems.
Here's another one:
This page loads in about 4-5 seconds with the fixes I described in 13351. Scrolling is still super slow though (which is worthy of a separate bug).
By "this page" I meant the attachment, not the URL I just pasted in two comments ago,.
The long-term solution to the blocks-inside-inlines problem is to avoid the creation of excess RenderObjects. Eliminate the concept of the continuation() and all of the inline splitting code and instead enable blocks to have a mixture of line and block children. The block could then alternate between line and block layout, as it goes through its mixture of lines and blocks.
The line boxes of a single <span> would then be connected as though the blocks weren't present.
First-line could also be simplified, since later lines after subblocks would know they weren't really the first line.
I am essentially proposing the elimination of the anonymous block in favor of a RenderBlock that understands how to lay out mixtures and thus doesn't need to create anonymous blocks in the first place.
Just brainstorming, but the basic idea would be to allow blocks inside inlines in the render tree. Do no fixups. The enclosing block thinks its children are inline. During line layout, hitting one of these blocks results in an end of the line. Then block layout has to run until an inline is again encountered. And so on, switching back and forth between the two layout models.
Here's the real stress test.
Pure inline nesting. No blocks.
I have landed a fix that takes care of blocks inside inlines nesting badly. Next up is a cap on the depth of the line box tree for a given single line. This should resolve the original test case as well as the penguin test case I just added.
I'm declaring victory.
We can file individual bugs for more slowness.