Changeset 213712 in webkit


Ignore:
Timestamp:
Mar 10, 2017 8:01:50 AM (7 years ago)
Author:
Antti Koivisto
Message:

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.
Location:
trunk
Files:
3 added
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r213706 r213712  
     12017-03-10  Antti Koivisto  <antti@apple.com>
     2
     3        Loading in-body stylesheets should not block rendering of elements before them
     4        https://bugs.webkit.org/show_bug.cgi?id=169345
     5
     6        Reviewed by Simon Fraser.
     7
     8        * http/tests/incremental/resources/delayed-css.php: Added.
     9        * http/tests/incremental/stylesheet-body-incremental-rendering-expected.html: Added.
     10        * http/tests/incremental/stylesheet-body-incremental-rendering.html: Added.
     11
    1122017-03-10  Antoine Quint  <graouts@apple.com>
    213
  • trunk/Source/WebCore/ChangeLog

    r213711 r213712  
     12017-03-10  Antti Koivisto  <antti@apple.com>
     2
     3        Allow the page to render before <link> stylesheet tags in body
     4        https://bugs.webkit.org/show_bug.cgi?id=149157
     5        <rdar://problem/24658830>
     6
     7        Reviewed by Simon Fraser.
     8
     9        Currently we block style and renderer building completely if document has any loading
     10        stylesheets. In case a script queries something layout dependent we construct the render
     11        tree with whatever style we have but block painting in it.
     12
     13        This patch changes behavior so that a loading stylesheet in body only blocks rendering for elements
     14        that are after it. The expectation is that such stylesheets rarely affect elements before them
     15        and the elements can be rendered without causing ugly visible styling changes.
     16
     17        The patch replaces the old flash-of-unstyled-content (FOUC) preventation mechanism with a more
     18        fine-grained one. Paint blocking is now done on per-renderer basis with based on isNonFinal flag in
     19        RenderStyle.
     20
     21        For stylesheets in head the behavior should be largely unchanged.
     22
     23        Test: http/tests/incremental/stylesheet-body-incremental-rendering.html
     24
     25        * css/StyleResolver.cpp:
     26        (WebCore::StyleResolver::pseudoStyleRulesForElement):
     27        * dom/Document.cpp:
     28        (WebCore::Document::Document):
     29        (WebCore::Document::resolveStyle):
     30        (WebCore::Document::updateLayoutIgnorePendingStylesheets):
     31
     32            Remove the old FOUC preventation state tracking.
     33
     34        (WebCore::Document::shouldScheduleLayout):
     35        (WebCore::Document::didRemoveAllPendingStylesheet):
     36
     37            Repaints will now get triggered by the normal style mechanism.
     38
     39        * dom/Document.h:
     40        (WebCore::Document::hasNodesWithNonFinalStyle):
     41        (WebCore::Document::setHasNodesWithNonFinalStyle):
     42
     43            Track if we need to recompute the style later because non-final or unstyled elements.
     44
     45        (WebCore::Document::didLayoutWithPendingStylesheets): Deleted.
     46        (WebCore::Document::hasNodesWithPlaceholderStyle): Deleted.
     47        (WebCore::Document::setHasNodesWithPlaceholderStyle): Deleted.
     48        * html/HTMLFrameSetElement.cpp:
     49        (WebCore::HTMLFrameSetElement::rendererIsNeeded):
     50        * page/FrameView.cpp:
     51        (WebCore::FrameView::qualifiesAsVisuallyNonEmpty):
     52
     53            Don't qualify as visually non-empty if we have loading stylesheets in head (even if there is
     54            a fouc-prevented render tree).
     55
     56        (WebCore::FrameView::fireLayoutRelatedMilestonesIfNeeded):
     57        * rendering/RenderBlock.cpp:
     58        (WebCore::RenderBlock::paintContents):
     59
     60            Instead of a global test, block painting if isNonFinal is set in the renderer's style.
     61
     62        * rendering/RenderLayer.cpp:
     63        (WebCore::shouldSuppressPaintingLayer):
     64        * rendering/style/RenderStyle.cpp:
     65        (WebCore::RenderStyle::changeRequiresRepaint):
     66
     67            The isNonFinal flag prevents painting so we need to trigger repaint when it gets cleared.
     68
     69        * rendering/style/RenderStyle.h:
     70        (WebCore::RenderStyle::isNotFinal):
     71        (WebCore::RenderStyle::setIsNotFinal):
     72        (WebCore::RenderStyle::isPlaceholderStyle): Deleted.
     73        (WebCore::RenderStyle::setIsPlaceholderStyle): Deleted.
     74
     75            There is no need for placeholder styles anymore. Reuse the bit for isNotFinal.
     76
     77        * rendering/style/StyleRareNonInheritedData.cpp:
     78        (WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
     79        (WebCore::StyleRareNonInheritedData::operator==):
     80        * rendering/style/StyleRareNonInheritedData.h:
     81        * style/StyleScope.cpp:
     82        (WebCore::Style::Scope::analyzeStyleSheetChange):
     83        (WebCore::Style::Scope::updateActiveStyleSheets):
     84        * style/StyleTreeResolver.cpp:
     85        (WebCore::Style::TreeResolver::styleForElement):
     86        (WebCore::Style::TreeResolver::resolveElement):
     87
     88            If we have seens a loading stylesheet and don't have a renderer yet don't style the element.
     89            In case there is a renderer or we are ignoring pending sheets, resolve the style normally
     90            but mark it as non-final.
     91
     92        (WebCore::Style::makePlaceholderStyle): Deleted.
     93
    1942017-03-10  Antti Koivisto  <antti@apple.com>
    295
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r213701 r213712  
    11241124Vector<RefPtr<StyleRule>> StyleResolver::pseudoStyleRulesForElement(const Element* element, PseudoId pseudoId, unsigned rulesToInclude)
    11251125{
    1126     if (!element || !element->document().haveStylesheetsLoaded())
    1127         return Vector<RefPtr<StyleRule>>();
     1126    if (!element)
     1127        return { };
    11281128
    11291129    m_state = State(*element, nullptr);
  • trunk/Source/WebCore/dom/Document.cpp

    r213701 r213712  
    443443    , m_referencingNodeCount(0)
    444444    , m_settings(frame ? Ref<Settings>(frame->settings()) : Settings::create(nullptr))
    445     , m_hasNodesWithPlaceholderStyle(false)
     445    , m_hasNodesWithNonFinalStyle(false)
    446446    , m_ignorePendingStylesheets(false)
    447     , m_pendingSheetLayout(NoLayoutWithPendingSheets)
    448447    , m_cachedResourceLoader(m_frame ? Ref<CachedResourceLoader>(m_frame->loader().activeDocumentLoader()->cachedResourceLoader()) : CachedResourceLoader::create(nullptr))
    449448    , m_activeParserCount(0)
     
    17831782        if (type == ResolveStyleType::Rebuild) {
    17841783            // This may get set again during style resolve.
    1785             m_hasNodesWithPlaceholderStyle = false;
     1784            m_hasNodesWithNonFinalStyle = false;
    17861785
    17871786            auto documentStyle = Style::resolveForDocument(*this);
     
    18191818
    18201819        updatedCompositingLayers = frameView.updateCompositingLayersAfterStyleChange();
     1820
     1821        if (m_renderView->needsLayout())
     1822            frameView.scheduleRelayout();
    18211823    }
    18221824
     
    19121914}
    19131915
    1914 // FIXME: This is a bad idea and needs to be removed eventually.
    1915 // Other browsers load stylesheets before they continue parsing the web page.
    1916 // Since we don't, we can run JavaScript code that needs answers before the
    1917 // stylesheets are loaded. Doing a layout ignoring the pending stylesheets
    1918 // lets us get reasonable answers. The long term solution to this problem is
    1919 // to instead suspend JavaScript execution.
    19201916void Document::updateLayoutIgnorePendingStylesheets(Document::RunPostLayoutTasks runPostLayoutTasks)
    19211917{
     
    19241920    if (!haveStylesheetsLoaded()) {
    19251921        m_ignorePendingStylesheets = true;
    1926         // FIXME: We are willing to attempt to suppress painting with outdated style info only once.  Our assumption is that it would be
    1927         // dangerous to try to stop it a second time, after page content has already been loaded and displayed
    1928         // with accurate style information.  (Our suppression involves blanking the whole page at the
    1929         // moment.  If it were more refined, we might be able to do something better.)
    1930         // It's worth noting though that this entire method is a hack, since what we really want to do is
    1931         // suspend JS instead of doing a layout with inaccurate information.
    1932         HTMLElement* bodyElement = bodyOrFrameset();
    1933         if (bodyElement && !bodyElement->renderer() && m_pendingSheetLayout == NoLayoutWithPendingSheets) {
    1934             m_pendingSheetLayout = DidLayoutWithPendingSheets;
    1935             styleScope().didChangeActiveStyleSheetCandidates();
    1936             resolveStyle(ResolveStyleType::Rebuild);
    1937         } else if (m_hasNodesWithPlaceholderStyle)
    1938             // If new nodes have been added or style recalc has been done with style sheets still pending, some nodes
    1939             // may not have had their real style calculated yet. Normally this gets cleaned when style sheets arrive
    1940             // but here we need up-to-date style immediately.
     1922        // FIXME: This should just invalidate elements with non-final styles.
     1923        if (m_hasNodesWithNonFinalStyle)
    19411924            resolveStyle(ResolveStyleType::Rebuild);
    19421925    }
     
    27722755bool Document::shouldScheduleLayout()
    27732756{
    2774     // This function will only be called when FrameView thinks a layout is needed.
    2775     // This enforces a couple extra rules.
    2776     //
    2777     //    (a) Only schedule a layout once the stylesheets are loaded.
    2778     //    (b) Only schedule layout once we have a body element.
    2779 
    2780     return (haveStylesheetsLoaded() && bodyOrFrameset())
    2781         || (documentElement() && !is<HTMLHtmlElement>(*documentElement()));
     2757    if (!documentElement())
     2758        return false;
     2759    if (!is<HTMLHtmlElement>(*documentElement()))
     2760        return true;
     2761    if (!bodyOrFrameset())
     2762        return false;
     2763    if (styleScope().hasPendingSheetsBeforeBody())
     2764        return false;
     2765
     2766    return true;
    27822767}
    27832768   
     
    30833068void Document::didRemoveAllPendingStylesheet()
    30843069{
    3085     if (m_pendingSheetLayout == DidLayoutWithPendingSheets) {
    3086         // Painting is disabled when doing layouts with pending sheets to avoid FOUC.
    3087         // We need to force paint when coming out from this state.
    3088         // FIXME: This is not very elegant.
    3089         m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
    3090         if (renderView())
    3091             renderView()->repaintViewAndCompositedLayers();
    3092     }
    3093 
    30943070    if (auto* parser = scriptableDocumentParser())
    30953071        parser->executeScriptsWaitingForStylesheetsSoon();
  • trunk/Source/WebCore/dom/Document.h

    r213701 r213712  
    937937    WEBCORE_EXPORT ExceptionOr<Ref<XPathResult>> evaluate(const String& expression, Node* contextNode, RefPtr<XPathNSResolver>&&, unsigned short type, XPathResult*);
    938938
    939     enum PendingSheetLayout { NoLayoutWithPendingSheets, DidLayoutWithPendingSheets, IgnoreLayoutWithPendingSheets };
    940 
    941     bool didLayoutWithPendingStylesheets() const { return m_pendingSheetLayout == DidLayoutWithPendingSheets; }
    942 
    943     bool hasNodesWithPlaceholderStyle() const { return m_hasNodesWithPlaceholderStyle; }
    944     void setHasNodesWithPlaceholderStyle() { m_hasNodesWithPlaceholderStyle = true; }
     939    bool hasNodesWithNonFinalStyle() const { return m_hasNodesWithNonFinalStyle; }
     940    void setHasNodesWithNonFinalStyle() { m_hasNodesWithNonFinalStyle = true; }
    945941
    946942    void updateFocusAppearanceSoon(SelectionRestorationMode);
     
    13861382
    13871383    std::unique_ptr<StyleResolver> m_userAgentShadowTreeStyleResolver;
    1388     bool m_hasNodesWithPlaceholderStyle;
     1384    bool m_hasNodesWithNonFinalStyle;
    13891385    // But sometimes you need to ignore pending stylesheet count to
    13901386    // force an immediate layout when requested by JS.
    13911387    bool m_ignorePendingStylesheets;
    1392 
    1393     // If we do ignore the pending stylesheet count, then we need to add a boolean
    1394     // to track that this happened so that we can do a full repaint when the stylesheets
    1395     // do eventually load.
    1396     PendingSheetLayout m_pendingSheetLayout;
    13971388
    13981389    RefPtr<DOMWindow> m_domWindow;
  • trunk/Source/WebCore/html/HTMLFrameSetElement.cpp

    r213701 r213712  
    154154    // For compatibility, frames render even when display: none is set.
    155155    // However, we delay creating a renderer until stylesheets have loaded.
    156     return !style.isPlaceholderStyle();
     156    return !style.isNotFinal();
    157157}
    158158
  • trunk/Source/WebCore/page/FrameView.cpp

    r213701 r213712  
    46304630        return true;
    46314631
     4632    // FIXME: We should also ignore renderers with non-final style.
     4633    if (frame().document()->styleScope().hasPendingSheetsBeforeBody())
     4634        return false;
     4635
    46324636    // Require the document to grow a bit.
    46334637    // Using a value of 48 allows the header on Google's search page to render immediately before search results populate later.
     
    51725176
    51735177    // If the layout was done with pending sheets, we are not in fact visually non-empty yet.
    5174     if (m_isVisuallyNonEmpty && !frame().document()->didLayoutWithPendingStylesheets() && m_firstVisuallyNonEmptyLayoutCallbackPending) {
     5178    if (m_isVisuallyNonEmpty &&m_firstVisuallyNonEmptyLayoutCallbackPending) {
    51755179        m_firstVisuallyNonEmptyLayoutCallbackPending = false;
    51765180        if (requestedMilestones & DidFirstVisuallyNonEmptyLayout)
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r213701 r213712  
    15701570void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
    15711571{
    1572     // Avoid painting descendants of the root element when stylesheets haven't loaded.  This eliminates FOUC.
    1573     // It's ok not to draw, because later on, when all the stylesheets do load, styleResolverChanged() on the Document
    1574     // will do a full repaint.
    1575     if (document().didLayoutWithPendingStylesheets() && !isRenderView())
     1572    // Style is non-final if the element has a pending stylesheet before it. We end up with renderers with such styles if a script
     1573    // forces renderer construction by querying something layout dependent.
     1574    // Avoid FOUC by not painting. Switching to final style triggers repaint.
     1575    if (style().isNotFinal())
    15761576        return;
    15771577
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r213701 r213712  
    39403940static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
    39413941{
    3942     // Avoid painting descendants of the root layer when stylesheets haven't loaded. This eliminates FOUC.
    3943     // It's ok not to draw, because later on, when all the stylesheets do load, updateStyleSelector on the Document
    3944     // will do a full repaint().
    3945     if (layer->renderer().document().didLayoutWithPendingStylesheets() && !layer->isRootLayer() && !layer->renderer().isDocumentElementRenderer())
     3942    if (layer->renderer().style().isNotFinal() && !layer->isRootLayer() && !layer->renderer().isDocumentElementRenderer())
    39463943        return true;
    39473944
  • trunk/Source/WebCore/rendering/style/RenderStyle.cpp

    r213701 r213712  
    854854        return true;
    855855
     856    if (m_rareNonInheritedData->isNotFinal != other.m_rareNonInheritedData->isNotFinal)
     857        return true;
     858
    856859    if (m_rareNonInheritedData->shapeOutside != other.m_rareNonInheritedData->shapeOutside)
    857860        return true;
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r213701 r213712  
    16541654#endif
    16551655
    1656     bool isPlaceholderStyle() const { return m_rareNonInheritedData->isPlaceholderStyle; }
    1657     void setIsPlaceholderStyle() { SET_VAR(m_rareNonInheritedData, isPlaceholderStyle, true); }
     1656    // Indicates the style is likely to change due to a pending stylesheet load.
     1657    bool isNotFinal() const { return m_rareNonInheritedData->isNotFinal; }
     1658    void setIsNotFinal() { SET_VAR(m_rareNonInheritedData, isNotFinal, true); }
    16581659
    16591660    void setVisitedLinkColor(const Color&);
  • trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp

    r213701 r213712  
    108108    , resize(RenderStyle::initialResize())
    109109    , hasAttrContent(false)
    110     , isPlaceholderStyle(false)
     110    , isNotFinal(false)
    111111{
    112112    maskBoxImage.setMaskDefaults();
     
    201201    , resize(o.resize)
    202202    , hasAttrContent(o.hasAttrContent)
    203     , isPlaceholderStyle(o.isPlaceholderStyle)
     203    , isNotFinal(o.isNotFinal)
    204204{
    205205}
     
    305305        && resize == o.resize
    306306        && hasAttrContent == o.hasAttrContent
    307         && isPlaceholderStyle == o.isPlaceholderStyle;
     307        && isNotFinal == o.isNotFinal;
    308308}
    309309
  • trunk/Source/WebCore/rendering/style/StyleRareNonInheritedData.h

    r213701 r213712  
    221221    unsigned hasAttrContent : 1;
    222222
    223     unsigned isPlaceholderStyle : 1;
     223    unsigned isNotFinal : 1;
    224224
    225225private:
  • trunk/Source/WebCore/style/StyleScope.cpp

    r213701 r213712  
    390390
    391391    // If we are already parsing the body and so may have significant amount of elements, put some effort into trying to avoid style recalcs.
    392     if (!m_document.bodyOrFrameset() || m_document.hasNodesWithPlaceholderStyle())
     392    if (!m_document.bodyOrFrameset() || m_document.hasNodesWithNonFinalStyle())
    393393        return styleResolverUpdateType;
    394394
     
    441441    // Don't bother updating, since we haven't loaded all our style info yet
    442442    // and haven't calculated the style resolver for the first time.
    443     if (!m_shadowRoot && !m_didUpdateActiveStyleSheets && hasPendingSheets()) {
     443    if (!m_shadowRoot && !m_didUpdateActiveStyleSheets && hasPendingSheetsBeforeBody()) {
    444444        clearResolver();
    445445        return;
  • trunk/Source/WebCore/style/StyleTreeResolver.cpp

    r213701 r213712  
    5252namespace Style {
    5353
    54 static std::unique_ptr<RenderStyle> makePlaceholderStyle(Document& document)
    55 {
    56     auto placeholderStyle = RenderStyle::createPtr();
    57     placeholderStyle->setDisplay(NONE);
    58     placeholderStyle->setIsPlaceholderStyle();
    59 
    60     FontCascadeDescription fontDescription;
    61     fontDescription.setOneFamily(standardFamily);
    62     fontDescription.setKeywordSizeFromIdentifier(CSSValueMedium);
    63     float size = Style::fontSizeForKeyword(CSSValueMedium, false, document);
    64     fontDescription.setSpecifiedSize(size);
    65     fontDescription.setComputedSize(size);
    66     placeholderStyle->setFontDescription(fontDescription);
    67 
    68     placeholderStyle->fontCascade().update(&document.fontSelector());
    69     return placeholderStyle;
    70 }
    71 
    7254TreeResolver::TreeResolver(Document& document)
    7355    : m_document(document)
     
    127109std::unique_ptr<RenderStyle> TreeResolver::styleForElement(Element& element, const RenderStyle& inheritedStyle)
    128110{
    129     if (m_didSeePendingStylesheet && !element.renderer() && !m_document.isIgnoringPendingStylesheets()) {
    130         m_document.setHasNodesWithPlaceholderStyle();
    131         return makePlaceholderStyle(m_document);
    132     }
    133 
    134111    if (element.hasCustomStyleResolveCallbacks()) {
    135112        RenderStyle* shadowHostStyle = scope().shadowRoot ? m_update->elementStyle(*scope().shadowRoot->host()) : nullptr;
     
    191168ElementUpdate TreeResolver::resolveElement(Element& element)
    192169{
     170    if (m_didSeePendingStylesheet && !element.renderer() && !m_document.isIgnoringPendingStylesheets()) {
     171        m_document.setHasNodesWithNonFinalStyle();
     172        return { };
     173    }
     174
    193175    auto newStyle = styleForElement(element, parent().style);
    194176
     
    196178        return { };
    197179
     180    auto* existingStyle = element.renderStyle();
     181
     182    if (m_didSeePendingStylesheet && (!existingStyle || existingStyle->isNotFinal())) {
     183        newStyle->setIsNotFinal();
     184        m_document.setHasNodesWithNonFinalStyle();
     185    }
     186
    198187    auto update = createAnimatedElementUpdate(WTFMove(newStyle), element, parent().change);
    199 
    200     auto* existingStyle = element.renderStyle();
    201188
    202189    if (&element == m_document.documentElement()) {
Note: See TracChangeset for help on using the changeset viewer.