Source/WebCore:
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Mar 2017 22:56:32 +0000 (22:56 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 27 Mar 2017 22:56:32 +0000 (22:56 +0000)
commitfb1530dc985c68eafa68a70457da409f9e27e223
treebe6d5fe69dfaa2b047ea1ff51dc31a591b16ded9
parent46e2f14caea3a64e9d9fbe4734faf76ffaf18954
Source/WebCore:
Allow the page to render before <link> stylesheet tags in body
https://bugs.webkit.org/show_bug.cgi?id=149157
<rdar://problem/24658830>

Reviewed by Simon Fraser.

Currently we block style and renderer building completely if document has any loading
stylesheets. In case a script queries something layout dependent we construct the render
tree with whatever style we have but block painting in it.

This patch changes behavior so that a loading stylesheet in body only blocks rendering for elements
that are after it. The expectation is that such stylesheets rarely affect elements before them
and the elements can be rendered without causing ugly visible styling changes.

The patch replaces the old flash-of-unstyled-content (FOUC) preventation mechanism with a more
fine-grained one. Paint blocking is now done on per-renderer basis with based on isNonFinal flag in
RenderStyle.

For stylesheets in head the behavior should be largely unchanged.

Test: http/tests/incremental/stylesheet-body-incremental-rendering.html

* css/StyleResolver.cpp:
(WebCore::StyleResolver::pseudoStyleRulesForElement):
* dom/Document.cpp:
(WebCore::Document::Document):
(WebCore::Document::resolveStyle):
(WebCore::Document::updateLayoutIgnorePendingStylesheets):

    Remove the old FOUC preventation state tracking.

(WebCore::Document::shouldScheduleLayout):
(WebCore::Document::didRemoveAllPendingStylesheet):

    Repaints will now get triggered by the normal style mechanism.

* dom/Document.h:
(WebCore::Document::hasNodesWithNonFinalStyle):
(WebCore::Document::setHasNodesWithNonFinalStyle):

    Track if we need to recompute the style later because non-final or unstyled elements.

(WebCore::Document::didLayoutWithPendingStylesheets): Deleted.
(WebCore::Document::hasNodesWithPlaceholderStyle): Deleted.
(WebCore::Document::setHasNodesWithPlaceholderStyle): Deleted.
* html/HTMLFrameSetElement.cpp:
(WebCore::HTMLFrameSetElement::rendererIsNeeded):
* page/FrameView.cpp:
(WebCore::FrameView::qualifiesAsVisuallyNonEmpty):

    Don't qualify as visually non-empty if we have loading stylesheets in head (even if there is
    a fouc-prevented render tree).

(WebCore::FrameView::fireLayoutRelatedMilestonesIfNeeded):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paintContents):

    Instead of a global test, block painting if isNonFinal is set in the renderer's style.

* rendering/RenderLayer.cpp:
(WebCore::shouldSuppressPaintingLayer):
* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::changeRequiresRepaint):

    The isNonFinal flag prevents painting so we need to trigger repaint when it gets cleared.

* rendering/style/RenderStyle.h:
(WebCore::RenderStyle::isNotFinal):
(WebCore::RenderStyle::setIsNotFinal):
(WebCore::RenderStyle::isPlaceholderStyle): Deleted.
(WebCore::RenderStyle::setIsPlaceholderStyle): Deleted.

    There is no need for placeholder styles anymore. Reuse the bit for isNotFinal.

* rendering/style/StyleRareNonInheritedData.cpp:
(WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
(WebCore::StyleRareNonInheritedData::operator==):
* rendering/style/StyleRareNonInheritedData.h:
* style/StyleScope.cpp:
(WebCore::Style::Scope::analyzeStyleSheetChange):
(WebCore::Style::Scope::updateActiveStyleSheets):
* style/StyleTreeResolver.cpp:
(WebCore::Style::TreeResolver::styleForElement):
(WebCore::Style::TreeResolver::resolveElement):

    If we have seens a loading stylesheet and don't have a renderer yet don't style the element.
    In case there is a renderer or we are ignoring pending sheets, resolve the style normally
    but mark it as non-final.

(WebCore::Style::makePlaceholderStyle): Deleted.

LayoutTests:
Loading in-body stylesheets should not block rendering of elements before them
https://bugs.webkit.org/show_bug.cgi?id=169345

Reviewed by Simon Fraser.

* http/tests/incremental/resources/delayed-css.php: Added.
* http/tests/incremental/stylesheet-body-incremental-rendering-expected.html: Added.
* http/tests/incremental/stylesheet-body-incremental-rendering.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214435 268f45cc-cd09-0410-ab3c-d52691b4dbfc
17 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/incremental/stylesheet-body-incremental-rendering-expected.html [new file with mode: 0644]
LayoutTests/http/tests/incremental/stylesheet-body-incremental-rendering.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/html/HTMLFrameSetElement.cpp
Source/WebCore/page/FrameView.cpp
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/style/RenderStyle.cpp
Source/WebCore/rendering/style/RenderStyle.h
Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
Source/WebCore/rendering/style/StyleRareNonInheritedData.h
Source/WebCore/style/StyleScope.cpp
Source/WebCore/style/StyleTreeResolver.cpp