Changeset 198943 in webkit


Ignore:
Timestamp:
Apr 1, 2016 2:54:12 AM (8 years ago)
Author:
Antti Koivisto
Message:

Separate render tree updating from style resolve
https://bugs.webkit.org/show_bug.cgi?id=155298

Reviewed by Andreas Kling.

Source/WebCore:

This patch splits computing document style and applying the results into two distinct steps:

Style::TreeResolver::resolve()

|
| Style::Update
V

RenderTreeUpdater::commit()

Style::TreeResolver::resolve() returns a Style::Update object that contains all the changes to be made
for the whole composed tree. RenderTreeUpdater then applies the changes updating, building or tearing
down portions of the render tree as needed.

Style::Update consists of a map that contains new style for each newly resolved element along with some
metadata. A separate map contains text nodes that require reconstruction. It also tracks change roots so
RenderTreeUpdater needs to traverse the changed subtrees only.

The patch eliminates the recursive render tree build code path replacing it with iterative functions.

This will enable future optimizations. For example we won't need to commit to immediate rendering
changes simply because some script or internal function requires up-to-date style.

  • CMakeLists.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • css/StyleResolver.cpp:

(WebCore::StyleResolver::State::State):
(WebCore::StyleResolver::styleForElement):

  • css/StyleResolver.h:

(WebCore::StyleResolver::setOverrideDocumentElementStyle):
(WebCore::StyleResolver::State::State):

Root element style is needed for resolving other elements. Add a way to provide it without looking
into active document style.

  • dom/Document.cpp:

(WebCore::Document::recalcStyle):

Resolve the document style and commit it immediately (for now).

(WebCore::Document::styleForElementIgnoringPendingStylesheets):

  • dom/Document.h:

(WebCore::Document::setNeedsNotifyRemoveAllPendingStylesheet):
(WebCore::Document::inStyleRecalc):
(WebCore::Document::inRenderTreeUpdate):

  • dom/Element.cpp:

(WebCore::Element::setChildIndex):

Setting the unique bit is now done by style relations update code.

  • dom/Node.cpp:

(WebCore::Node::setNeedsStyleRecalc):

Prevent spurious style invalidation during render tree updating.

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::styleDidChange):

Capturing body element color for color:-webkit-text is now done by TreeResolver.

  • rendering/RenderElement.h:

(WebCore::RenderElement::setAnimatableStyle): Deleted.

No longer used.

  • style/RenderTreePosition.cpp:

(WebCore::RenderTreePosition::nextSiblingRenderer):

Skip over non-rendered slot elements.

  • style/RenderTreeUpdater.cpp: Added.

(WebCore::RenderTreeUpdater::Parent::Parent):
(WebCore::RenderTreeUpdater::RenderTreeUpdater):
(WebCore::hasDisplayContents):
(WebCore::findRenderingRoot):
(WebCore::RenderTreeUpdater::commit):

Call updateRenderTree for each change root.

(WebCore::shouldCreateRenderer):
(WebCore::RenderTreeUpdater::updateRenderTree):

Iteratively traverse the composed tree starting for a change root.
Apply the changes calling updateElementRenderer and updateTextRenderer as needed.
Enter subtrees that haves changes to apply.

(WebCore::RenderTreeUpdater::renderTreePosition):

We may not create renderers for all elements (<slot> or more generally display:contents) that
have rendered descendants. Search the parent stack to find the valid position.

(WebCore::RenderTreeUpdater::pushParent):
(WebCore::RenderTreeUpdater::popParent):
(WebCore::RenderTreeUpdater::popParentsToDepth):

Maintain parent stack.

(WebCore::pseudoStyleCacheIsInvalid):
(WebCore::RenderTreeUpdater::updateElementRenderer):

Create, delete or update the renderer.

(WebCore::moveToFlowThreadIfNeeded):
(WebCore::RenderTreeUpdater::createRenderer):
(WebCore::textRendererIsNeeded):
(WebCore::createTextRenderer):
(WebCore::RenderTreeUpdater::updateTextRenderer):
(WebCore::RenderTreeUpdater::invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded):

This is moved from TreeResolver.

(WebCore::needsPseudoElement):
(WebCore::RenderTreeUpdater::updateBeforeOrAfterPseudoElement):

Pseudo elements are handled entirely during render tree construction. Compute their style and
create or delete them as needed.

  • style/RenderTreeUpdater.h: Added.

(WebCore::RenderTreeUpdater::parent):

  • style/StyleRelations.cpp:

(WebCore::Style::commitRelationsToRenderStyle):
(WebCore::Style::commitRelations):

Commit to Style::Update instead of the document if needed.

(WebCore::Style::commitRelationsToDocument): Deleted.

  • style/StyleRelations.h:
  • style/StyleSharingResolver.cpp:

(WebCore::Style::elementHasDirectionAuto):
(WebCore::Style::SharingResolver::resolve):

Fetch the shareable style from Style::Update instead of the active document style.

(WebCore::Style::SharingResolver::findSibling):
(WebCore::Style::SharingResolver::canShareStyleWithElement):

  • style/StyleSharingResolver.h:
  • style/StyleTreeResolver.cpp:

(WebCore::Style::TreeResolver::Parent::Parent):

No need for render tree position anymore.

(WebCore::Style::TreeResolver::popScope):
(WebCore::Style::TreeResolver::styleForElement):
(WebCore::Style::invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded):
(WebCore::Style::createTextRendererIfNeeded):
(WebCore::Style::updateTextRendererAfterContentChange):
(WebCore::Style::resetStyleForNonRenderedDescendants):
(WebCore::Style::detachChildren):
(WebCore::Style::detachSlotAssignees):
(WebCore::Style::detachRenderTree):
(WebCore::Style::TreeResolver::resolveElement):

Just resolve the style and return it, no more applying or entering render tree construction code paths.

(WebCore::Style::resolveTextNode):
(WebCore::Style::elementImplicitVisibility):
(WebCore::Style::TreeResolver::pushParent):
(WebCore::Style::TreeResolver::popParent):
(WebCore::Style::TreeResolver::popParentsToDepth):
(WebCore::Style::shouldResolvePseudoElement):
(WebCore::Style::TreeResolver::resolveComposedTree):

Add style changes to Style::Update.

(WebCore::Style::TreeResolver::resolve):

Return Style::Update object if non-empty.

(WebCore::Style::postResolutionCallbackQueue):
(WebCore::Style::shouldCreateRenderer): Deleted.
(WebCore::Style::moveToFlowThreadIfNeeded): Deleted.
(WebCore::Style::TreeResolver::createRenderer): Deleted.
(WebCore::Style::TreeResolver::createRenderTreeForChildren): Deleted.
(WebCore::Style::TreeResolver::createRenderTreeForShadowRoot): Deleted.
(WebCore::Style::beforeOrAfterPseudoElement): Deleted.
(WebCore::Style::setBeforeOrAfterPseudoElement): Deleted.
(WebCore::Style::clearBeforeOrAfterPseudoElement): Deleted.
(WebCore::Style::needsPseudoElement): Deleted.
(WebCore::Style::TreeResolver::createRenderTreeForBeforeOrAfterPseudoElement): Deleted.
(WebCore::Style::TreeResolver::createRenderTreeForSlotAssignees): Deleted.
(WebCore::Style::TreeResolver::createRenderTreeRecursively): Deleted.
(WebCore::Style::pseudoStyleCacheIsInvalid): Deleted.
(WebCore::Style::TreeResolver::resolveBeforeOrAfterPseudoElement): Deleted.

Remove the recursive render tree building code path.

  • style/StyleTreeResolver.h:

(WebCore::Style::TreeResolver::scope):

  • style/StyleUpdate.cpp: Added.

(WebCore::Style::Update::Update):
(WebCore::Style::Update::elementUpdate):
(WebCore::Style::Update::textUpdate):
(WebCore::Style::Update::elementStyle):
(WebCore::Style::Update::addElement):
(WebCore::Style::Update::addText):
(WebCore::Style::Update::addPossibleRoot):

  • style/StyleUpdate.h: Added.

(WebCore::Style::Update::roots):
(WebCore::Style::Update::document):

  • svg/SVGElement.h:

(WebCore::SVGElement::updateRelativeLengthsInformation):

  • svg/SVGUseElement.cpp:

(WebCore::SVGUseElement::svgAttributeChanged):
(WebCore::SVGUseElement::willRecalcStyle):
(WebCore::SVGUseElement::willAttachRenderers): Deleted.

Switvh willAttachRenderers to willRecalcStyle as the former is now called too late.

  • svg/SVGUseElement.h:

LayoutTests:

Skip mathml/presentation/menclose-notation-attribute-change-value.html. It will be fixed by upcoming MathML refactoring.

  • css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt:
  • css3/viewport-percentage-lengths/viewport-percentage-lengths-resize-expected.txt:

This is a progression.

  • editing/mac/spelling/autocorrection-contraction-expected.txt:
  • editing/mac/spelling/autocorrection-removing-underline-after-paste-expected.txt:
  • editing/mac/spelling/autocorrection-removing-underline-expected.txt:
  • editing/mac/spelling/autocorrection-simple-expected.txt:
  • editing/style/remove-underline-from-stylesheet-expected.txt:
  • editing/style/typing-style-003-expected.txt:

Non-rendered whitespace related changes.

  • platform/ios-simulator/TestExpectations:

Skip fast/regions/position-writing-modes-in-variable-width-regions.html on iOS. Similar tests are mostly already skipped.

  • platform/ios-simulator/editing/style/typing-style-003-expected.txt: Added.
  • platform/mac-wk2/editing/mac/spelling/autocorrection-contraction-expected.txt:
  • platform/mac/editing/inserting/editable-html-element-expected.txt:
  • platform/mac/editing/inserting/editing-empty-divs-expected.txt:
  • platform/mac/editing/inserting/insert-at-end-02-expected.txt:
  • platform/mac/editing/pasteboard/4989774-expected.txt:
  • platform/mac/editing/selection/4983858-expected.txt:

Non-rendered whitespace related changes.

Location:
trunk
Files:
5 added
41 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r198942 r198943  
     12016-03-31  Antti Koivisto  <antti@apple.com>
     2
     3        Separate render tree updating from style resolve
     4        https://bugs.webkit.org/show_bug.cgi?id=155298
     5
     6        Reviewed by Andreas Kling.
     7
     8        * TestExpectations:
     9
     10            Skip mathml/presentation/menclose-notation-attribute-change-value.html. It will be fixed by upcoming MathML refactoring.
     11
     12        * css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt:
     13        * css3/viewport-percentage-lengths/viewport-percentage-lengths-resize-expected.txt:
     14
     15            This is a progression.
     16
     17        * editing/mac/spelling/autocorrection-contraction-expected.txt:
     18        * editing/mac/spelling/autocorrection-removing-underline-after-paste-expected.txt:
     19        * editing/mac/spelling/autocorrection-removing-underline-expected.txt:
     20        * editing/mac/spelling/autocorrection-simple-expected.txt:
     21        * editing/style/remove-underline-from-stylesheet-expected.txt:
     22        * editing/style/typing-style-003-expected.txt:
     23
     24            Non-rendered whitespace related changes.
     25
     26        * platform/ios-simulator/TestExpectations:
     27
     28            Skip fast/regions/position-writing-modes-in-variable-width-regions.html on iOS. Similar tests are mostly already skipped.
     29
     30        * platform/ios-simulator/editing/style/typing-style-003-expected.txt: Added.
     31        * platform/mac-wk2/editing/mac/spelling/autocorrection-contraction-expected.txt:
     32        * platform/mac/editing/inserting/editable-html-element-expected.txt:
     33        * platform/mac/editing/inserting/editing-empty-divs-expected.txt:
     34        * platform/mac/editing/inserting/insert-at-end-02-expected.txt:
     35        * platform/mac/editing/pasteboard/4989774-expected.txt:
     36        * platform/mac/editing/selection/4983858-expected.txt:
     37
     38            Non-rendered whitespace related changes.
     39
    1402016-03-31  Chris Fleizach  <cfleizach@apple.com>
    241
  • trunk/LayoutTests/TestExpectations

    r198888 r198943  
    991991webkit.org/b/155028 storage/indexeddb/modern/256-open-databases.html [ Skip ]
    992992
     993# Fixed by upcoming MathML refactoring
     994webkit.org/b/155019 mathml/presentation/menclose-notation-attribute-change-value.html [ Skip ]
     995
    993996### END OF IndexedDB failures
    994997########################################
  • trunk/LayoutTests/css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt

    r198847 r198943  
    2222  (rect 28 290 60 60)
    2323  (rect 48 290 60 60)
     24  (rect 28 526 60 60)
     25  (rect 48 526 60 60)
    2426  (rect 48 408 60 60)
    2527  (rect 48 408 60 60)
    26   (rect 28 526 60 60)
    27   (rect 48 526 60 60)
    2828  (rect 48 644 60 60)
    2929  (rect 68 644 60 60)
  • trunk/LayoutTests/css3/viewport-percentage-lengths/viewport-percentage-lengths-resize-expected.txt

    r198847 r198943  
    1818PASS getComputedStyle(test).width is "450px"
    1919PASS getComputedStyle(testpseudo, ':after').marginLeft is "120px"
    20 FAIL getComputedStyle(testpseudo, ':after').paddingRight should be 225px. Was 200px.
     20PASS getComputedStyle(testpseudo, ':after').paddingRight is "225px"
    2121PASS innerWidth is 900
    2222PASS innerHeight is 640
    2323PASS getComputedStyle(test).fontSize is "32px"
    2424PASS getComputedStyle(test).width is "450px"
    25 FAIL getComputedStyle(testpseudo, ':after').marginLeft should be 128px. Was 120px.
    26 FAIL getComputedStyle(testpseudo, ':after').paddingRight should be 225px. Was 200px.
     25PASS getComputedStyle(testpseudo, ':after').marginLeft is "128px"
     26PASS getComputedStyle(testpseudo, ':after').paddingRight is "225px"
    2727PASS innerWidth is 500
    2828PASS innerHeight is 640
    2929PASS getComputedStyle(test).fontSize is "32px"
    3030PASS getComputedStyle(test).width is "250px"
    31 FAIL getComputedStyle(testpseudo, ':after').marginLeft should be 100px. Was 120px.
    32 FAIL getComputedStyle(testpseudo, ':after').paddingRight should be 160px. Was 200px.
     31PASS getComputedStyle(testpseudo, ':after').marginLeft is "100px"
     32PASS getComputedStyle(testpseudo, ':after').paddingRight is "160px"
    3333PASS innerWidth is 800
    3434PASS innerHeight is 600
  • trunk/LayoutTests/editing/mac/spelling/autocorrection-contraction-expected.txt

    r198847 r198943  
    280280            text run at (0,0) width 154: "would' wouldn't"
    281281            text run at (153,0) width 7: " "
    282 caret: position 16 of child 0 {#text} of child 5 {DIV} of child 3 {DIV} of body
     282caret: position 16 of child 0 {#text} of child 6 {DIV} of child 3 {DIV} of body
  • trunk/LayoutTests/editing/mac/spelling/autocorrection-removing-underline-after-paste-expected.txt

    r198847 r198943  
    8383        RenderBlock {DIV} at (14,70) size 756x28
    8484          RenderBR {BR} at (0,0) size 0x28
    85 caret: position 0 of child 0 {BR} of child 4 {DIV} of child 5 {DIV} of body
     85caret: position 0 of child 0 {BR} of child 5 {DIV} of child 5 {DIV} of body
  • trunk/LayoutTests/editing/mac/spelling/autocorrection-removing-underline-expected.txt

    r198847 r198943  
    7979        RenderBlock {DIV} at (14,42) size 756x28
    8080          RenderBR {BR} at (0,0) size 0x28
    81 caret: position 0 of child 0 {BR} of child 2 {DIV} of child 5 {DIV} of body
     81caret: position 0 of child 0 {BR} of child 3 {DIV} of child 5 {DIV} of body
  • trunk/LayoutTests/editing/mac/spelling/autocorrection-simple-expected.txt

    r198847 r198943  
    138138          RenderText {#text} at (0,0) size 138x28
    139139            text run at (0,0) width 138: "the notational,"
    140 caret: position 15 of child 0 {#text} of child 2 {DIV} of child 7 {DIV} of body
     140caret: position 15 of child 0 {#text} of child 3 {DIV} of child 7 {DIV} of body
  • trunk/LayoutTests/editing/style/remove-underline-from-stylesheet-expected.txt

    r198847 r198943  
    7777| "<#selection-anchor>xxxxxx<#selection-focus>"
    7878| " xxxxxx"
     79| "
     80"
    7981| <span>
    8082|   id="test"
  • trunk/LayoutTests/editing/style/typing-style-003-expected.txt

    r198847 r198943  
    5353xxxxxxxxxxxxxxx
    5454execTypeCharacterCommand: x <span id="test"></span>
    55 execTypeCharacterCommand: xx<span id="test"></span>
    56 execTypeCharacterCommand: xxx<span id="test"></span>
    57 execBoldCommand: xxx<span id="test"></span>
    58 execTypeCharacterCommand: xxx<b>x</b><span id="test"></span>
     55execTypeCharacterCommand: xx <span id="test"></span>
     56execTypeCharacterCommand: xxx <span id="test"></span>
     57execBoldCommand: xxx <span id="test"></span>
     58execTypeCharacterCommand: xxx<b>x</b> <span id="test"></span>
    5959execTypeCharacterCommand: xxx<b>xx</b><span id="test"></span>
    6060execTypeCharacterCommand: xxx<b>xxx</b><span id="test"></span>
  • trunk/LayoutTests/fast/dom/beforeload/remove-bad-object-in-beforeload-listener-expected.txt

    r61721 r198943  
    22
    33PASS
     4
  • trunk/LayoutTests/fast/dom/beforeload/remove-flash-in-beforeload-listener-expected.txt

    r61744 r198943  
    22
    33PASS
     4
  • trunk/LayoutTests/platform/ios-simulator/TestExpectations

    r198936 r198943  
    20542054fast/regions/percentage-margins-rtl-variable-width-regions.html [ ImageOnlyFailure ]
    20552055fast/regions/percentage-margins-variable-width-regions.html [ ImageOnlyFailure ]
     2056fast/regions/position-writing-modes-in-variable-width-regions.html [ ImageOnlyFailure ]
    20562057fast/regions/positioning/fixed-in-named-flow-position-changed.html [ ImageOnlyFailure ]
    20572058fast/regions/positioning/fixed-inside-fixed-in-named-flow.html [ ImageOnlyFailure ]
  • trunk/LayoutTests/platform/mac-wk2/editing/mac/spelling/autocorrection-contraction-expected.txt

    r198847 r198943  
    260260            text run at (0,0) width 166: "wouldn' wouldn't"
    261261            text run at (165,0) width 7: " "
    262 caret: position 17 of child 0 {#text} of child 5 {DIV} of child 3 {DIV} of body
     262caret: position 17 of child 0 {#text} of child 6 {DIV} of child 3 {DIV} of body
  • trunk/LayoutTests/platform/mac/editing/inserting/editable-html-element-expected.txt

    r198847 r198943  
    2323          text run at (766,18) width 5: " "
    2424          text run at (0,36) width 132: "block flow element)."
    25         RenderText {#text} at (0,0) size 0x0
    2625      RenderBlock {DIV} at (0,54) size 784x18
    2726        RenderBR {BR} at (0,0) size 0x18
  • trunk/LayoutTests/platform/mac/editing/inserting/editing-empty-divs-expected.txt

    r198847 r198943  
    6666        RenderText {#text} at (1,1) size 8x18
    6767          text run at (1,1) width 8: "c"
    68         RenderText {#text} at (0,0) size 0x0
    6968      RenderBlock {P} at (0,268) size 784x18
    7069        RenderText {#text} at (0,0) size 240x18
     
    8281          RenderText {#text} at (0,0) size 8x18
    8382            text run at (0,0) width 8: "c"
    84           RenderText {#text} at (0,0) size 0x0
    8583        RenderBlock {P} at (1,35) size 706x0
    8684caret: position 1 of child 0 {#text} of child 21 {DIV} of body
  • trunk/LayoutTests/platform/mac/editing/inserting/insert-at-end-02-expected.txt

    r198847 r198943  
    3030          RenderText {#text} at (0,0) size 8x18
    3131            text run at (0,0) width 8: "x"
    32           RenderText {#text} at (0,0) size 0x0
    3332caret: position 1 of child 5 {#text} of child 5 {DIV} of body
  • trunk/LayoutTests/platform/mac/editing/pasteboard/4989774-expected.txt

    r198847 r198943  
    1313        text run at (735,103) width 5: " "
    1414        text run at (0,121) width 364: "several pictures above all in the same line/paragraph."
    15       RenderText {#text} at (0,0) size 0x0
    16       RenderText {#text} at (0,0) size 0x0
    1715caret: position 164 of child 4 {#text} of body
  • trunk/LayoutTests/platform/mac/editing/selection/4983858-expected.txt

    r198847 r198943  
    1111          text run at (780,0) width 4: " "
    1212          text run at (0,18) width 165: "below should be selected:"
    13         RenderText {#text} at (0,0) size 0x0
    1413      RenderBlock {DIV} at (0,36) size 784x18
    1514        RenderText {#text} at (0,0) size 22x18
  • trunk/LayoutTests/plugins/focus-expected.txt

    r147591 r198943  
    2525
    2626   Fallback contents.     Fallback contents. Fallback contents.     
     27
  • trunk/Source/WebCore/CMakeLists.txt

    r198942 r198943  
    26282628    style/InlineTextBoxStyle.cpp
    26292629    style/RenderTreePosition.cpp
     2630    style/RenderTreeUpdater.cpp
    26302631    style/StyleChange.cpp
    26312632    style/StyleFontSizeFunctions.cpp
     
    26342635    style/StyleSharingResolver.cpp
    26352636    style/StyleTreeResolver.cpp
     2637    style/StyleUpdate.cpp
    26362638
    26372639    svg/SVGAElement.cpp
  • trunk/Source/WebCore/ChangeLog

    r198942 r198943  
     12016-03-31  Antti Koivisto  <antti@apple.com>
     2
     3        Separate render tree updating from style resolve
     4        https://bugs.webkit.org/show_bug.cgi?id=155298
     5
     6        Reviewed by Andreas Kling.
     7
     8        This patch splits computing document style and applying the results into two distinct steps:
     9
     10        Style::TreeResolver::resolve()
     11                |
     12                | Style::Update
     13                V
     14        RenderTreeUpdater::commit()
     15
     16        Style::TreeResolver::resolve() returns a Style::Update object that contains all the changes to be made
     17        for the whole composed tree. RenderTreeUpdater then applies the changes updating, building or tearing
     18        down portions of the render tree as needed.
     19
     20        Style::Update consists of a map that contains new style for each newly resolved element along with some
     21        metadata. A separate map contains text nodes that require reconstruction. It also tracks change roots so
     22        RenderTreeUpdater needs to traverse the changed subtrees only.
     23
     24        The patch eliminates the recursive render tree build code path replacing it with iterative functions.
     25
     26        This will enable future optimizations. For example we won't need to commit to immediate rendering
     27        changes simply because some script or internal function requires up-to-date style.
     28
     29        * CMakeLists.txt:
     30        * WebCore.xcodeproj/project.pbxproj:
     31        * css/StyleResolver.cpp:
     32        (WebCore::StyleResolver::State::State):
     33        (WebCore::StyleResolver::styleForElement):
     34        * css/StyleResolver.h:
     35        (WebCore::StyleResolver::setOverrideDocumentElementStyle):
     36        (WebCore::StyleResolver::State::State):
     37
     38            Root element style is needed for resolving other elements. Add a way to provide it without looking
     39            into active document style.
     40
     41        * dom/Document.cpp:
     42        (WebCore::Document::recalcStyle):
     43
     44            Resolve the document style and commit it immediately (for now).
     45
     46        (WebCore::Document::styleForElementIgnoringPendingStylesheets):
     47        * dom/Document.h:
     48        (WebCore::Document::setNeedsNotifyRemoveAllPendingStylesheet):
     49        (WebCore::Document::inStyleRecalc):
     50        (WebCore::Document::inRenderTreeUpdate):
     51        * dom/Element.cpp:
     52        (WebCore::Element::setChildIndex):
     53
     54            Setting the unique bit is now done by style relations update code.
     55
     56        * dom/Node.cpp:
     57        (WebCore::Node::setNeedsStyleRecalc):
     58
     59            Prevent spurious style invalidation during render tree updating.
     60
     61        * rendering/RenderBox.cpp:
     62        (WebCore::RenderBox::styleDidChange):
     63
     64            Capturing body element color for color:-webkit-text is now done by TreeResolver.
     65
     66        * rendering/RenderElement.h:
     67        (WebCore::RenderElement::setAnimatableStyle): Deleted.
     68
     69            No longer used.
     70
     71        * style/RenderTreePosition.cpp:
     72        (WebCore::RenderTreePosition::nextSiblingRenderer):
     73
     74            Skip over non-rendered slot elements.
     75
     76        * style/RenderTreeUpdater.cpp: Added.
     77        (WebCore::RenderTreeUpdater::Parent::Parent):
     78        (WebCore::RenderTreeUpdater::RenderTreeUpdater):
     79        (WebCore::hasDisplayContents):
     80        (WebCore::findRenderingRoot):
     81        (WebCore::RenderTreeUpdater::commit):
     82
     83            Call updateRenderTree for each change root.
     84
     85        (WebCore::shouldCreateRenderer):
     86        (WebCore::RenderTreeUpdater::updateRenderTree):
     87
     88            Iteratively traverse the composed tree starting for a change root.
     89            Apply the changes calling updateElementRenderer and updateTextRenderer as needed.
     90            Enter subtrees that haves changes to apply.
     91
     92        (WebCore::RenderTreeUpdater::renderTreePosition):
     93
     94            We may not create renderers for all elements (<slot> or more generally display:contents) that
     95            have rendered descendants. Search the parent stack to find the valid position.
     96
     97        (WebCore::RenderTreeUpdater::pushParent):
     98        (WebCore::RenderTreeUpdater::popParent):
     99        (WebCore::RenderTreeUpdater::popParentsToDepth):
     100
     101            Maintain parent stack.
     102
     103        (WebCore::pseudoStyleCacheIsInvalid):
     104        (WebCore::RenderTreeUpdater::updateElementRenderer):
     105
     106            Create, delete or update the renderer.
     107
     108        (WebCore::moveToFlowThreadIfNeeded):
     109        (WebCore::RenderTreeUpdater::createRenderer):
     110        (WebCore::textRendererIsNeeded):
     111        (WebCore::createTextRenderer):
     112        (WebCore::RenderTreeUpdater::updateTextRenderer):
     113        (WebCore::RenderTreeUpdater::invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded):
     114
     115            This is moved from TreeResolver.
     116
     117        (WebCore::needsPseudoElement):
     118        (WebCore::RenderTreeUpdater::updateBeforeOrAfterPseudoElement):
     119
     120            Pseudo elements are handled entirely during render tree construction. Compute their style and
     121            create or delete them as needed.
     122
     123        * style/RenderTreeUpdater.h: Added.
     124        (WebCore::RenderTreeUpdater::parent):
     125        * style/StyleRelations.cpp:
     126        (WebCore::Style::commitRelationsToRenderStyle):
     127        (WebCore::Style::commitRelations):
     128
     129            Commit to Style::Update instead of the document if needed.
     130
     131        (WebCore::Style::commitRelationsToDocument): Deleted.
     132        * style/StyleRelations.h:
     133        * style/StyleSharingResolver.cpp:
     134        (WebCore::Style::elementHasDirectionAuto):
     135        (WebCore::Style::SharingResolver::resolve):
     136
     137            Fetch the shareable style from Style::Update instead of the active document style.
     138
     139        (WebCore::Style::SharingResolver::findSibling):
     140        (WebCore::Style::SharingResolver::canShareStyleWithElement):
     141        * style/StyleSharingResolver.h:
     142        * style/StyleTreeResolver.cpp:
     143        (WebCore::Style::TreeResolver::Parent::Parent):
     144
     145            No need for render tree position anymore.
     146
     147        (WebCore::Style::TreeResolver::popScope):
     148        (WebCore::Style::TreeResolver::styleForElement):
     149        (WebCore::Style::invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded):
     150        (WebCore::Style::createTextRendererIfNeeded):
     151        (WebCore::Style::updateTextRendererAfterContentChange):
     152        (WebCore::Style::resetStyleForNonRenderedDescendants):
     153        (WebCore::Style::detachChildren):
     154        (WebCore::Style::detachSlotAssignees):
     155        (WebCore::Style::detachRenderTree):
     156        (WebCore::Style::TreeResolver::resolveElement):
     157
     158            Just resolve the style and return it, no more applying or entering render tree construction code paths.
     159
     160        (WebCore::Style::resolveTextNode):
     161        (WebCore::Style::elementImplicitVisibility):
     162        (WebCore::Style::TreeResolver::pushParent):
     163        (WebCore::Style::TreeResolver::popParent):
     164        (WebCore::Style::TreeResolver::popParentsToDepth):
     165        (WebCore::Style::shouldResolvePseudoElement):
     166        (WebCore::Style::TreeResolver::resolveComposedTree):
     167
     168            Add style changes to Style::Update.
     169
     170        (WebCore::Style::TreeResolver::resolve):
     171
     172            Return Style::Update object if non-empty.
     173
     174        (WebCore::Style::postResolutionCallbackQueue):
     175        (WebCore::Style::shouldCreateRenderer): Deleted.
     176        (WebCore::Style::moveToFlowThreadIfNeeded): Deleted.
     177        (WebCore::Style::TreeResolver::createRenderer): Deleted.
     178        (WebCore::Style::TreeResolver::createRenderTreeForChildren): Deleted.
     179        (WebCore::Style::TreeResolver::createRenderTreeForShadowRoot): Deleted.
     180        (WebCore::Style::beforeOrAfterPseudoElement): Deleted.
     181        (WebCore::Style::setBeforeOrAfterPseudoElement): Deleted.
     182        (WebCore::Style::clearBeforeOrAfterPseudoElement): Deleted.
     183        (WebCore::Style::needsPseudoElement): Deleted.
     184        (WebCore::Style::TreeResolver::createRenderTreeForBeforeOrAfterPseudoElement): Deleted.
     185        (WebCore::Style::TreeResolver::createRenderTreeForSlotAssignees): Deleted.
     186        (WebCore::Style::TreeResolver::createRenderTreeRecursively): Deleted.
     187        (WebCore::Style::pseudoStyleCacheIsInvalid): Deleted.
     188        (WebCore::Style::TreeResolver::resolveBeforeOrAfterPseudoElement): Deleted.
     189
     190            Remove the recursive render tree building code path.
     191
     192        * style/StyleTreeResolver.h:
     193        (WebCore::Style::TreeResolver::scope):
     194        * style/StyleUpdate.cpp: Added.
     195        (WebCore::Style::Update::Update):
     196        (WebCore::Style::Update::elementUpdate):
     197        (WebCore::Style::Update::textUpdate):
     198        (WebCore::Style::Update::elementStyle):
     199        (WebCore::Style::Update::addElement):
     200        (WebCore::Style::Update::addText):
     201        (WebCore::Style::Update::addPossibleRoot):
     202        * style/StyleUpdate.h: Added.
     203        (WebCore::Style::Update::roots):
     204        (WebCore::Style::Update::document):
     205        * svg/SVGElement.h:
     206        (WebCore::SVGElement::updateRelativeLengthsInformation):
     207        * svg/SVGUseElement.cpp:
     208        (WebCore::SVGUseElement::svgAttributeChanged):
     209        (WebCore::SVGUseElement::willRecalcStyle):
     210        (WebCore::SVGUseElement::willAttachRenderers): Deleted.
     211
     212            Switvh willAttachRenderers to willRecalcStyle as the former is now called too late.
     213
     214        * svg/SVGUseElement.h:
     215
    12162016-03-31  Chris Fleizach  <cfleizach@apple.com>
    2217
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r198942 r198943  
    65606560                E425A49A18292B840020CFCF /* CollectionIndexCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E425A49918292B840020CFCF /* CollectionIndexCache.h */; };
    65616561                E4295FA412B0614E00D1ACE0 /* ResourceLoadPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */; settings = {ATTRIBUTES = (Private, ); }; };
     6562                E42E76DA1C7AF76C00E3614D /* StyleUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42E76D91C7AF76C00E3614D /* StyleUpdate.cpp */; };
     6563                E42E76DC1C7AF77600E3614D /* StyleUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = E42E76DB1C7AF77600E3614D /* StyleUpdate.h */; };
    65626564                E43105B816750F0C00DB2FB8 /* NodeTraversal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */; };
    65636565                E43105BB16750F1600DB2FB8 /* NodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E43105BA16750F1600DB2FB8 /* NodeTraversal.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    66156617                E453904D0EAFD637003695C8 /* WidgetIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = E453903C0EAFD637003695C8 /* WidgetIOS.mm */; };
    66166618                E45390AE0EAFF4B5003695C8 /* SystemMemoryIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E45390AD0EAFF4B5003695C8 /* SystemMemoryIOS.cpp */; };
     6619                E46180291C8A06CD0026C02C /* RenderTreeUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = E46180281C8A06CD0026C02C /* RenderTreeUpdater.h */; };
     6620                E461802B1C8A06D90026C02C /* RenderTreeUpdater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E461802A1C8A06D90026C02C /* RenderTreeUpdater.cpp */; };
    66176621                E461802D1C8DD2900026C02C /* StyleRelations.h in Headers */ = {isa = PBXBuildFile; fileRef = E461802C1C8DD2900026C02C /* StyleRelations.h */; };
    66186622                E461802F1C8DD4D20026C02C /* StyleRelations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E461802E1C8DD4D20026C02C /* StyleRelations.cpp */; };
     
    1459614600                E425A49918292B840020CFCF /* CollectionIndexCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionIndexCache.h; sourceTree = "<group>"; };
    1459714601                E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadPriority.h; sourceTree = "<group>"; };
     14602                E42E76D91C7AF76C00E3614D /* StyleUpdate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleUpdate.cpp; sourceTree = "<group>"; };
     14603                E42E76DB1C7AF77600E3614D /* StyleUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleUpdate.h; sourceTree = "<group>"; };
    1459814604                E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodeTraversal.cpp; sourceTree = "<group>"; };
    1459914605                E43105BA16750F1600DB2FB8 /* NodeTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeTraversal.h; sourceTree = "<group>"; };
     
    1464314649                E453903C0EAFD637003695C8 /* WidgetIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WidgetIOS.mm; sourceTree = "<group>"; };
    1464414650                E45390AD0EAFF4B5003695C8 /* SystemMemoryIOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SystemMemoryIOS.cpp; sourceTree = "<group>"; };
     14651                E46180281C8A06CD0026C02C /* RenderTreeUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeUpdater.h; sourceTree = "<group>"; };
     14652                E461802A1C8A06D90026C02C /* RenderTreeUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeUpdater.cpp; sourceTree = "<group>"; };
    1464514653                E461802C1C8DD2900026C02C /* StyleRelations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleRelations.h; sourceTree = "<group>"; };
    1464614654                E461802E1C8DD4D20026C02C /* StyleRelations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleRelations.cpp; sourceTree = "<group>"; };
     
    2351323521                                5824ABA81AE849C8009074B7 /* RenderTreePosition.cpp */,
    2351423522                                5824ABA91AE849C8009074B7 /* RenderTreePosition.h */,
     23523                                E461802A1C8A06D90026C02C /* RenderTreeUpdater.cpp */,
     23524                                E46180281C8A06CD0026C02C /* RenderTreeUpdater.h */,
    2351523525                                E401E0A51C3C0CF700F34D10 /* StyleChange.cpp */,
    2351623526                                E401E0A31C3C0B8300F34D10 /* StyleChange.h */,
     
    2352523535                                E4DEAA1517A93DC3000E0430 /* StyleTreeResolver.cpp */,
    2352623536                                E4DEAA1617A93DC3000E0430 /* StyleTreeResolver.h */,
     23537                                E42E76D91C7AF76C00E3614D /* StyleUpdate.cpp */,
     23538                                E42E76DB1C7AF77600E3614D /* StyleUpdate.h */,
    2352723539                        );
    2352823540                        path = style;
     
    2596025972                                7728694F14F8882500F484DC /* EXTTextureFilterAnisotropic.h in Headers */,
    2596125973                                A75E8B890E1DE2D6007F2481 /* FEBlend.h in Headers */,
     25974                                E46180291C8A06CD0026C02C /* RenderTreeUpdater.h in Headers */,
    2596225975                                A75E8B8B0E1DE2D6007F2481 /* FEColorMatrix.h in Headers */,
    2596325976                                A75E8B8D0E1DE2D6007F2481 /* FEComponentTransfer.h in Headers */,
     
    2615226165                                93F198E508245E59001E9ABC /* HTMLDocument.h in Headers */,
    2615326166                                977B3867122883E900B81FF8 /* HTMLDocumentParser.h in Headers */,
     26167                                E42E76DC1C7AF77600E3614D /* StyleUpdate.h in Headers */,
    2615426168                                93309DE8099E64920056E581 /* htmlediting.h in Headers */,
    2615526169                                93F198E608245E59001E9ABC /* HTMLElement.h in Headers */,
     
    3053830552                                E1FF8F64180745D800132674 /* JSSubtleCrypto.cpp in Sources */,
    3053930553                                E1FF8F681807460800132674 /* JSSubtleCryptoCustom.cpp in Sources */,
     30554                                E461802B1C8A06D90026C02C /* RenderTreeUpdater.cpp in Sources */,
    3054030555                                B20111070AB7740500DB0E68 /* JSSVGAElement.cpp in Sources */,
    3054130556                                24D9129113CA951E00D21915 /* JSSVGAltGlyphDefElement.cpp in Sources */,
     
    3107631091                                FD581FB41520F93B003A7A75 /* PeriodicWave.cpp in Sources */,
    3107731092                                49D5DC2D0F423A73008F20FD /* PerspectiveTransformOperation.cpp in Sources */,
     31093                                E42E76DA1C7AF76C00E3614D /* StyleUpdate.cpp in Sources */,
    3107831094                                D0FF2A5D11F8C45A007E74E0 /* PingLoader.cpp in Sources */,
    3107931095                                CD7D33431C7A123F00041293 /* PixelBufferConformerCV.cpp in Sources */,
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r198847 r198943  
    336336}
    337337
    338 StyleResolver::State::State(Element& element, RenderStyle* parentStyle, const RenderRegion* regionForStyling, const SelectorFilter* selectorFilter)
     338StyleResolver::State::State(Element& element, RenderStyle* parentStyle, RenderStyle* documentElementStyle, const RenderRegion* regionForStyling, const SelectorFilter* selectorFilter)
    339339    : m_element(&element)
    340340    , m_parentStyle(parentStyle)
     
    349349    auto& document = element.document();
    350350    auto* documentElement = document.documentElement();
    351     m_rootElementStyle = (!documentElement || documentElement == &element) ? document.renderStyle() : documentElement->renderStyle();
     351    if (!documentElement || documentElement == &element)
     352        m_rootElementStyle = document.renderStyle();
     353    else
     354        m_rootElementStyle = documentElementStyle ? documentElementStyle : documentElement->renderStyle();
    352355
    353356    updateConversionData();
     
    376379    RELEASE_ASSERT(!m_inLoadPendingImages);
    377380
    378     m_state = State(element, parentStyle, regionForStyling, selectorFilter);
     381    m_state = State(element, parentStyle, m_overrideDocumentElementStyle.get(), regionForStyling, selectorFilter);
    379382    State& state = m_state;
    380383
  • trunk/Source/WebCore/css/StyleResolver.h

    r198847 r198943  
    165165    const MediaQueryEvaluator& mediaQueryEvaluator() const { return *m_medium; }
    166166
     167    void setOverrideDocumentElementStyle(RenderStyle* style) { m_overrideDocumentElementStyle = style; }
     168
    167169private:
    168170    Ref<RenderStyle> styleForKeyframe(const RenderStyle*, const StyleKeyframe*, KeyframeValue&);
     
    360362    public:
    361363        State() { }
    362         State(Element&, RenderStyle* parentStyle, const RenderRegion* regionForStyling = nullptr, const SelectorFilter* = nullptr);
     364        State(Element&, RenderStyle* parentStyle, RenderStyle* documentElementStyle = nullptr, const RenderRegion* regionForStyling = nullptr, const SelectorFilter* = nullptr);
    363365
    364366    public:
     
    525527    bool m_matchAuthorAndUserStyles;
    526528
     529    RefPtr<RenderStyle> m_overrideDocumentElementStyle;
     530
    527531    Vector<std::unique_ptr<MediaQueryResult>> m_viewportDependentMediaQueryResults;
    528532
  • trunk/Source/WebCore/dom/Document.cpp

    r198847 r198943  
    134134#include "RenderChildIterator.h"
    135135#include "RenderLayerCompositor.h"
     136#include "RenderTreeUpdater.h"
    136137#include "RenderView.h"
    137138#include "RenderWidget.h"
     
    19271928
    19281929        Style::TreeResolver resolver(*this);
    1929         resolver.resolve(change);
    1930 
    1931         updatedCompositingLayers = frameView.updateCompositingLayersAfterStyleChange();
     1930        auto styleUpdate = resolver.resolve(change);
    19321931
    19331932        clearNeedsStyleRecalc();
     
    19361935
    19371936        m_inStyleRecalc = false;
     1937
     1938        if (styleUpdate) {
     1939            TemporaryChange<bool> inRenderTreeUpdate(m_inRenderTreeUpdate, true);
     1940
     1941            RenderTreeUpdater updater(*this);
     1942            updater.commit(WTFMove(styleUpdate));
     1943        }
     1944
     1945        updatedCompositingLayers = frameView.updateCompositingLayersAfterStyleChange();
    19381946    }
    19391947
     
    20532061    auto elementStyle = element.resolveStyle(parentStyle);
    20542062
    2055     Style::commitRelationsToDocument(WTFMove(elementStyle.relations));
     2063    if (elementStyle.relations) {
     2064        Style::Update emptyUpdate(*this);
     2065        Style::commitRelations(WTFMove(elementStyle.relations), emptyUpdate);
     2066    }
    20562067
    20572068    return WTFMove(elementStyle.renderStyle);
  • trunk/Source/WebCore/dom/Document.h

    r198847 r198943  
    12451245    void clearStyleResolver();
    12461246
    1247     bool inStyleRecalc() { return m_inStyleRecalc; }
     1247    bool inStyleRecalc() const { return m_inStyleRecalc; }
     1248    bool inRenderTreeUpdate() const { return m_inRenderTreeUpdate; }
    12481249
    12491250    // Return a Locale for the default locale if the argument is null or empty.
     
    15091510    bool m_inStyleRecalc;
    15101511    bool m_closeAfterStyleRecalc;
     1512    bool m_inRenderTreeUpdate { false };
    15111513
    15121514    bool m_gotoAnchorNeededAfterStylesheetsLoad;
  • trunk/Source/WebCore/dom/Element.cpp

    r198847 r198943  
    25652565{
    25662566    ElementRareData& rareData = ensureElementRareData();
    2567     if (RenderStyle* style = renderStyle())
    2568         style->setUnique();
    25692567    rareData.setChildIndex(index);
    25702568}
  • trunk/Source/WebCore/dom/Node.cpp

    r198847 r198943  
    773773        return;
    774774
     775    // FIXME: This should eventually be an ASSERT.
     776    if (document().inRenderTreeUpdate())
     777        return;
     778
    775779    StyleChangeType existingChangeType = styleChangeType();
    776780    if (changeType > existingChangeType)
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r198847 r198943  
    382382    bool isDocElementRenderer = isDocumentElementRenderer();
    383383
    384     // Set the text color if we're the body.
    385     if (isBodyRenderer)
    386         document().setTextColor(newStyle.visitedDependentColor(CSSPropertyColor));
    387 
    388384    if (isDocElementRenderer || isBodyRenderer) {
    389385        // Propagate the new writing mode and direction up to the RenderView.
  • trunk/Source/WebCore/rendering/RenderElement.h

    r198847 r198943  
    5151    void setStyle(Ref<RenderStyle>&&, StyleDifference minimalStyleDifference = StyleDifferenceEqual);
    5252
    53     // Called to update a style that is allowed to trigger animations.
    54     void setAnimatableStyle(Ref<RenderStyle>&&, StyleDifference minimalStyleDifference);
    55 
    5653    // The pseudo element style can be cached or uncached.  Use the cached method if the pseudo element doesn't respect
    5754    // any pseudo classes (and therefore has no concept of changing state).
     
    344341};
    345342
    346 inline void RenderElement::setAnimatableStyle(Ref<RenderStyle>&& style, StyleDifference minimalStyleDifference)
    347 {
    348     Ref<RenderStyle> animatedStyle = WTFMove(style);
    349     if (animation().updateAnimations(*this, animatedStyle, animatedStyle))
    350         minimalStyleDifference = std::max(minimalStyleDifference, StyleDifferenceRecompositeLayer);
    351    
    352     setStyle(WTFMove(animatedStyle), minimalStyleDifference);
    353 }
    354 
    355343inline void RenderElement::setAncestorLineBoxDirty(bool f)
    356344{
  • trunk/Source/WebCore/style/RenderTreePosition.cpp

    r198847 r198943  
    2828
    2929#include "ComposedTreeIterator.h"
     30#include "HTMLSlotElement.h"
    3031#include "PseudoElement.h"
    3132#include "RenderObject.h"
     
    8384        return nullptr;
    8485
    85     auto composedChildren = composedTreeChildren(*parentElement);
     86    auto composedDescendants = composedTreeDescendants(*parentElement);
     87    auto it = node.isBeforePseudoElement() ? composedDescendants.begin() : composedDescendants.at(node);
     88    auto end = composedDescendants.end();
    8689
    87     auto it = node.isBeforePseudoElement() ? composedChildren.begin() : composedChildren.at(node);
    88     for (auto end = composedChildren.end(); it != end; ++it) {
    89         RenderObject* renderer = it->renderer();
     90    while (it != end) {
     91        auto& node = *it;
     92        bool hasDisplayContents = is<HTMLSlotElement>(node);
     93        if (hasDisplayContents) {
     94            it.traverseNext();
     95            continue;
     96        }
     97        RenderObject* renderer = node.renderer();
    9098        if (renderer && !isRendererReparented(*renderer))
    9199            return renderer;
     100       
     101        it.traverseNextSkippingChildren();
    92102    }
    93103    if (PseudoElement* after = parentElement->afterPseudoElement())
  • trunk/Source/WebCore/style/StyleRelations.cpp

    r198847 r198943  
    3030#include "NodeRenderStyle.h"
    3131#include "RenderStyle.h"
     32#include "StyleUpdate.h"
    3233
    3334namespace WebCore {
     
    8687}
    8788
    88 void commitRelationsToDocument(std::unique_ptr<Relations> relations)
     89void commitRelations(std::unique_ptr<Relations> relations, Update& update)
    8990{
    9091    if (!relations)
     
    125126            break;
    126127        case Relation::FirstChild:
    127             if (auto* style = element.renderStyle())
     128            if (auto* style = update.elementStyle(element))
    128129                style->setFirstChildState();
    129130            break;
    130131        case Relation::LastChild:
    131             if (auto* style = element.renderStyle())
     132            if (auto* style = update.elementStyle(element))
    132133                style->setLastChildState();
    133134            break;
    134135        case Relation::NthChildIndex:
     136            if (auto* style = update.elementStyle(element))
     137                style->setUnique();
    135138            element.setChildIndex(relation.value);
    136139            break;
    137140        case Relation::Unique:
    138             if (auto* style = element.renderStyle())
     141            if (auto* style = update.elementStyle(element))
    139142                style->setUnique();
    140143            break;
  • trunk/Source/WebCore/style/StyleRelations.h

    r198847 r198943  
    3636namespace Style {
    3737
     38class Update;
     39
    3840struct Relation {
    3941    enum Type {
     
    6769
    6870std::unique_ptr<Relations> commitRelationsToRenderStyle(RenderStyle&, const Element&, const Relations&);
    69 void commitRelationsToDocument(std::unique_ptr<Relations>);
     71void commitRelations(std::unique_ptr<Relations>, Update&);
    7072
    7173}
  • trunk/Source/WebCore/style/StyleSharingResolver.cpp

    r198847 r198943  
    3434#include "RenderStyle.h"
    3535#include "SVGElement.h"
     36#include "StyleUpdate.h"
    3637#include "StyledElement.h"
    3738#include "VisitedLinkState.h"
     
    4546
    4647struct SharingResolver::Context {
     48    const Update& update;
    4749    const StyledElement& element;
    4850    bool elementAffectedByClassRules;
     
    6870}
    6971
    70 RefPtr<RenderStyle> SharingResolver::resolve(const Element& searchElement)
     72RefPtr<RenderStyle> SharingResolver::resolve(const Element& searchElement, const Update& update)
    7173{
    7274    if (!is<StyledElement>(searchElement))
     
    7880    if (parentElement.shadowRoot())
    7981        return nullptr;
    80     if (!parentElement.renderStyle())
     82    if (!update.elementStyle(parentElement))
    8183        return nullptr;
    8284    // If the element has inline style it is probably unique.
     
    9698
    9799    Context context {
     100        update,
    98101        element,
    99102        element.hasClass() && classNamesAffectedByRules(element.classNames()),
     
    128131    m_elementsSharingStyle.add(&element, shareElement);
    129132
    130     return RenderStyle::clone(shareElement->renderStyle());
     133    return RenderStyle::clone(update.elementStyle(*shareElement));
    131134}
    132135
     
    196199{
    197200    auto& element = context.element;
    198     auto* style = candidateElement.renderStyle();
     201    auto* style = context.update.elementStyle(candidateElement);
    199202    if (!style)
    200203        return false;
  • trunk/Source/WebCore/style/StyleSharingResolver.h

    r198847 r198943  
    4343namespace Style {
    4444
     45class Update;
     46
    4547class SharingResolver {
    4648public:
    4749    SharingResolver(const Document&, const DocumentRuleSets&, const SelectorFilter&);
    4850
    49     RefPtr<RenderStyle> resolve(const Element&);
     51    RefPtr<RenderStyle> resolve(const Element&, const Update&);
    5052
    5153private:
  • trunk/Source/WebCore/style/StyleTreeResolver.cpp

    r198847 r198943  
    55 *           (C) 2001 Dirk Mueller (mueller@kde.org)
    66 *           (C) 2007 David Smith (catfish.man@gmail.com)
    7  * Copyright (C) 2004-2010, 2012-2014 Apple Inc. All rights reserved.
     7 * Copyright (C) 2004-2010, 2012-2016 Apple Inc. All rights reserved.
    88 *           (C) 2007 Eric Seidel (eric@webkit.org)
    99 *
     
    2727#include "StyleTreeResolver.h"
    2828
    29 #include "AXObjectCache.h"
    30 #include "AnimationController.h"
    3129#include "AuthorStyleSheets.h"
    3230#include "CSSFontSelector.h"
     
    3432#include "ComposedTreeIterator.h"
    3533#include "ElementIterator.h"
    36 #include "ElementRareData.h"
    37 #include "FlowThreadController.h"
     34#include "HTMLBodyElement.h"
    3835#include "HTMLSlotElement.h"
    39 #include "InspectorInstrumentation.h"
    4036#include "LoaderStrategy.h"
    4137#include "MainFrame.h"
    4238#include "NodeRenderStyle.h"
    43 #include "NodeTraversal.h"
    4439#include "PlatformStrategies.h"
    45 #include "RenderFullScreen.h"
    46 #include "RenderNamedFlowThread.h"
    47 #include "RenderText.h"
    48 #include "RenderTreePosition.h"
    49 #include "RenderWidget.h"
    5040#include "Settings.h"
    5141#include "ShadowRoot.h"
     
    6151namespace Style {
    6252
    63 enum DetachType { NormalDetach, ReattachDetach };
    64 
    6553static void attachTextRenderer(Text&, RenderTreePosition&);
    66 static void detachRenderTree(Element&, DetachType);
    6754static void resolveTextNode(Text&, RenderTreePosition&);
    6855
     
    115102}
    116103
     104TreeResolver::~TreeResolver()
     105{
     106}
     107
    117108TreeResolver::Scope::Scope(Document& document)
    118109    : styleResolver(document.ensureStyleResolver())
     
    132123    : element(nullptr)
    133124    , style(*document.renderStyle())
    134     , renderTreePosition(*document.renderView())
    135125    , change(change)
    136126{
    137127}
    138128
    139 TreeResolver::Parent::Parent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change)
     129TreeResolver::Parent::Parent(Element& element, ElementUpdate& update)
    140130    : element(&element)
    141     , style(style)
    142     , renderTreePosition(renderTreePosition)
    143     , change(change)
     131    , style(*update.style)
     132    , change(update.change)
    144133{
    145134}
     
    159148{
    160149    return m_scopeStack.removeLast();
    161 }
    162 
    163 static bool shouldCreateRenderer(const Element& element, const RenderElement& parentRenderer)
    164 {
    165     if (!element.document().shouldCreateRenderers())
    166         return false;
    167     if (!parentRenderer.canHaveChildren() && !(element.isPseudoElement() && parentRenderer.canHaveGeneratedChildren()))
    168         return false;
    169     if (parentRenderer.element() && !parentRenderer.element()->childShouldCreateRenderer(element))
    170         return false;
    171     return true;
    172150}
    173151
     
    179157    }
    180158
     159    scope().styleResolver.setOverrideDocumentElementStyle(m_documentElementStyle.get());
     160
    181161    if (element.hasCustomStyleResolveCallbacks()) {
    182         RenderStyle* shadowHostStyle = scope().shadowRoot ? scope().shadowRoot->host()->renderStyle() : nullptr;
     162        RenderStyle* shadowHostStyle = scope().shadowRoot ? m_update->elementStyle(*scope().shadowRoot->host()) : nullptr;
    183163        if (auto customStyle = element.resolveCustomStyle(inheritedStyle, shadowHostStyle)) {
    184             Style::commitRelationsToDocument(WTFMove(customStyle->relations));
     164            if (customStyle->relations)
     165                commitRelations(WTFMove(customStyle->relations), *m_update);
     166
    185167            return WTFMove(customStyle->renderStyle);
    186168        }
    187169    }
    188170
    189     if (auto style = scope().sharingResolver.resolve(element))
     171    if (auto style = scope().sharingResolver.resolve(element, *m_update))
    190172        return *style;
    191173
    192174    auto elementStyle = scope().styleResolver.styleForElement(element, &inheritedStyle, MatchAllRules, nullptr, &scope().selectorFilter);
    193175
    194     Style::commitRelationsToDocument(WTFMove(elementStyle.relations));
     176    if (elementStyle.relations)
     177        commitRelations(WTFMove(elementStyle.relations), *m_update);
     178
    195179    return WTFMove(elementStyle.renderStyle);
    196 }
    197 
    198 #if ENABLE(CSS_REGIONS)
    199 static RenderNamedFlowThread* moveToFlowThreadIfNeeded(Element& element, const RenderStyle& style)
    200 {
    201     if (!element.shouldMoveToFlowThread(style))
    202         return 0;
    203 
    204     FlowThreadController& flowThreadController = element.document().renderView()->flowThreadController();
    205     RenderNamedFlowThread& parentFlowRenderer = flowThreadController.ensureRenderFlowThreadWithName(style.flowThread());
    206     flowThreadController.registerNamedFlowContentElement(element, parentFlowRenderer);
    207     return &parentFlowRenderer;
    208 }
    209 #endif
    210 
    211 void TreeResolver::createRenderer(Element& element, RenderTreePosition& renderTreePosition, RefPtr<RenderStyle>&& resolvedStyle)
    212 {
    213     ASSERT(shouldCreateRenderer(element, renderTreePosition.parent()));
    214     ASSERT(resolvedStyle);
    215 
    216     RenderNamedFlowThread* parentFlowRenderer = 0;
    217 #if ENABLE(CSS_REGIONS)
    218     parentFlowRenderer = moveToFlowThreadIfNeeded(element, *resolvedStyle);
    219 #endif
    220 
    221     if (!element.rendererIsNeeded(*resolvedStyle))
    222         return;
    223 
    224     renderTreePosition.computeNextSibling(element);
    225 
    226     RenderTreePosition insertionPosition = parentFlowRenderer
    227         ? RenderTreePosition(*parentFlowRenderer, parentFlowRenderer->nextRendererForElement(element))
    228         : renderTreePosition;
    229 
    230     RenderElement* newRenderer = element.createElementRenderer(resolvedStyle.releaseNonNull(), insertionPosition).leakPtr();
    231     if (!newRenderer)
    232         return;
    233     if (!insertionPosition.canInsert(*newRenderer)) {
    234         newRenderer->destroy();
    235         return;
    236     }
    237 
    238     // Make sure the RenderObject already knows it is going to be added to a RenderFlowThread before we set the style
    239     // for the first time. Otherwise code using inRenderFlowThread() in the styleWillChange and styleDidChange will fail.
    240     newRenderer->setFlowThreadState(insertionPosition.parent().flowThreadState());
    241 
    242     // Code below updateAnimations() can depend on Element::renderer() already being set.
    243     element.setRenderer(newRenderer);
    244 
    245     // FIXME: There's probably a better way to factor this.
    246     // This just does what setAnimatedStyle() does, except with setStyleInternal() instead of setStyle().
    247     Ref<RenderStyle> animatedStyle = newRenderer->style();
    248     newRenderer->animation().updateAnimations(*newRenderer, animatedStyle, animatedStyle);
    249     newRenderer->setStyleInternal(WTFMove(animatedStyle));
    250 
    251     newRenderer->initializeStyle();
    252 
    253 #if ENABLE(FULLSCREEN_API)
    254     if (m_document.webkitIsFullScreen() && m_document.webkitCurrentFullScreenElement() == &element) {
    255         newRenderer = RenderFullScreen::wrapRenderer(newRenderer, &insertionPosition.parent(), m_document);
    256         if (!newRenderer)
    257             return;
    258     }
    259 #endif
    260     // Note: Adding newRenderer instead of renderer(). renderer() may be a child of newRenderer.
    261     insertionPosition.insert(*newRenderer);
    262180}
    263181
     
    349267
    350268    textNode.setRenderer(newRenderer.get());
    351     // Parent takes care of the animations, no need to call setAnimatableStyle.
    352269    renderTreePosition.insert(*newRenderer.leakPtr());
    353270}
     
    382299}
    383300
    384 void TreeResolver::createRenderTreeForChildren(ContainerNode& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition)
    385 {
    386     for (Node* child = current.firstChild(); child; child = child->nextSibling()) {
    387         ASSERT((!child->renderer() || child->isNamedFlowContentNode()) || current.shadowRoot());
    388         if (child->renderer()) {
    389             renderTreePosition.invalidateNextSibling(*child->renderer());
    390             continue;
    391         }
    392         if (is<Text>(*child)) {
    393             attachTextRenderer(downcast<Text>(*child), renderTreePosition);
    394             continue;
    395         }
    396         if (is<Element>(*child))
    397             createRenderTreeRecursively(downcast<Element>(*child), inheritedStyle, renderTreePosition, nullptr);
    398     }
    399 }
    400 
    401 void TreeResolver::createRenderTreeForShadowRoot(ShadowRoot& shadowRoot)
    402 {
    403     ASSERT(shadowRoot.host());
    404     ASSERT(shadowRoot.host()->renderer());
    405 
    406     pushScope(shadowRoot);
    407 
    408     auto& renderer = *shadowRoot.host()->renderer();
    409     RenderTreePosition renderTreePosition(renderer);
    410     createRenderTreeForChildren(shadowRoot, renderer.style(), renderTreePosition);
    411 
    412     popScope();
    413 
    414     shadowRoot.clearNeedsStyleRecalc();
    415     shadowRoot.clearChildNeedsStyleRecalc();
    416 }
    417 
    418 static PseudoElement* beforeOrAfterPseudoElement(Element& current, PseudoId pseudoId)
    419 {
    420     ASSERT(pseudoId == BEFORE || pseudoId == AFTER);
    421     if (pseudoId == BEFORE)
    422         return current.beforePseudoElement();
    423     return current.afterPseudoElement();
    424 }
    425 
    426 static void setBeforeOrAfterPseudoElement(Element& current, Ref<PseudoElement>&& pseudoElement, PseudoId pseudoId)
    427 {
    428     ASSERT(pseudoId == BEFORE || pseudoId == AFTER);
    429     if (pseudoId == BEFORE) {
    430         current.setBeforePseudoElement(WTFMove(pseudoElement));
    431         return;
    432     }
    433     current.setAfterPseudoElement(WTFMove(pseudoElement));
    434 }
    435 
    436 static void clearBeforeOrAfterPseudoElement(Element& current, PseudoId pseudoId)
    437 {
    438     ASSERT(pseudoId == BEFORE || pseudoId == AFTER);
    439     if (pseudoId == BEFORE) {
    440         current.clearBeforePseudoElement();
    441         return;
    442     }
    443     current.clearAfterPseudoElement();
    444 }
    445 
    446301static void resetStyleForNonRenderedDescendants(Element& current)
    447302{
    448303    // FIXME: This is not correct with shadow trees. This should be done with ComposedTreeIterator.
    449     ASSERT(!current.renderer());
    450304    bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
    451305    for (auto& child : childrenOfType<Element>(current)) {
    452         ASSERT(!child.renderer());
    453306        bool affectedByPreviousSibling = child.styleIsAffectedByPreviousSibling() && elementNeedingStyleRecalcAffectsNextSiblingElementStyle;
    454307        if (child.needsStyleRecalc() || elementNeedingStyleRecalcAffectsNextSiblingElementStyle)
     
    465318        }
    466319    }
    467 }
    468 
    469 static bool needsPseudoElement(Element& current, PseudoId pseudoId)
    470 {
    471     if (!current.renderer() || !current.renderer()->canHaveGeneratedChildren())
    472         return false;
    473     if (current.isPseudoElement())
    474         return false;
    475     if (!pseudoElementRendererIsNeeded(current.renderer()->getCachedPseudoStyle(pseudoId)))
    476         return false;
    477     return true;
    478 }
    479 
    480 void TreeResolver::createRenderTreeForBeforeOrAfterPseudoElement(Element& current, PseudoId pseudoId, RenderTreePosition& renderTreePosition)
    481 {
    482     if (!needsPseudoElement(current, pseudoId))
    483         return;
    484     Ref<PseudoElement> pseudoElement = PseudoElement::create(current, pseudoId);
    485     InspectorInstrumentation::pseudoElementCreated(m_document.page(), pseudoElement.get());
    486     setBeforeOrAfterPseudoElement(current, pseudoElement.copyRef(), pseudoId);
    487     createRenderTreeRecursively(pseudoElement.get(), *current.renderStyle(), renderTreePosition, nullptr);
    488 }
    489 
    490 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
    491 void TreeResolver::createRenderTreeForSlotAssignees(HTMLSlotElement& slot, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition)
    492 {
    493     ASSERT(shouldCreateRenderer(slot, renderTreePosition.parent()));
    494 
    495     if (auto* assignedNodes = slot.assignedNodes()) {
    496         pushEnclosingScope();
    497         for (auto* child : *assignedNodes) {
    498             if (is<Text>(*child))
    499                 attachTextRenderer(downcast<Text>(*child), renderTreePosition);
    500             else if (is<Element>(*child))
    501                 createRenderTreeRecursively(downcast<Element>(*child), inheritedStyle, renderTreePosition, nullptr);
    502         }
    503         popScope();
    504     } else {
    505         SelectorFilterPusher selectorFilterPusher(scope().selectorFilter, slot);
    506         createRenderTreeForChildren(slot, inheritedStyle, renderTreePosition);
    507     }
    508 
    509     slot.clearNeedsStyleRecalc();
    510     slot.clearChildNeedsStyleRecalc();
    511 }
    512 #endif
    513 
    514 void TreeResolver::createRenderTreeRecursively(Element& current, RenderStyle& inheritedStyle, RenderTreePosition& renderTreePosition, RefPtr<RenderStyle>&& resolvedStyle)
    515 {
    516     ASSERT(!current.renderer());
    517 
    518     PostResolutionCallbackDisabler callbackDisabler(m_document);
    519     WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
    520 
    521     bool shouldCallCreateRenderer = shouldCreateRenderer(current, renderTreePosition.parent());
    522 
    523     RefPtr<RenderStyle> style = resolvedStyle;
    524     if (!style)
    525         style = styleForElement(current, inheritedStyle);
    526 
    527 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
    528     if (is<HTMLSlotElement>(current)) {
    529         if (shouldCallCreateRenderer && current.rendererIsNeeded(*style))
    530             createRenderTreeForSlotAssignees(downcast<HTMLSlotElement>(current), inheritedStyle, renderTreePosition);
    531         return;
    532     }
    533 #endif
    534 
    535     if (current.hasCustomStyleResolveCallbacks())
    536         current.willAttachRenderers();
    537 
    538     if (shouldCallCreateRenderer)
    539         createRenderer(current, renderTreePosition, style.releaseNonNull());
    540 
    541     if (auto* renderer = current.renderer()) {
    542         SelectorFilterPusher selectorFilterPusher(scope().selectorFilter, current, SelectorFilterPusher::NoPush);
    543 
    544         RenderTreePosition childRenderTreePosition(*renderer);
    545         createRenderTreeForBeforeOrAfterPseudoElement(current, BEFORE, childRenderTreePosition);
    546 
    547         auto* shadowRoot = current.shadowRoot();
    548         if (shadowRoot) {
    549             selectorFilterPusher.push();
    550             createRenderTreeForShadowRoot(*shadowRoot);
    551         } else if (current.firstChild())
    552             selectorFilterPusher.push();
    553 
    554         bool skipChildren = shadowRoot;
    555         if (!skipChildren)
    556             createRenderTreeForChildren(current, renderer->style(), childRenderTreePosition);
    557 
    558         if (AXObjectCache* cache = m_document.axObjectCache())
    559             cache->updateCacheAfterNodeIsAttached(&current);
    560 
    561         createRenderTreeForBeforeOrAfterPseudoElement(current, AFTER, childRenderTreePosition);
    562 
    563         current.updateFocusAppearanceAfterAttachIfNeeded();
    564     } else
    565         resetStyleForNonRenderedDescendants(current);
    566 
    567     current.clearNeedsStyleRecalc();
    568     current.clearChildNeedsStyleRecalc();
    569 
    570     if (current.hasCustomStyleResolveCallbacks())
    571         current.didAttachRenderers();
    572320}
    573321
     
    607355#endif
    608356
    609 static void detachRenderTree(Element& current, DetachType detachType)
     357void detachRenderTree(Element& current, DetachType detachType)
    610358{
    611359    WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
     
    638386}
    639387
    640 static bool pseudoStyleCacheIsInvalid(RenderElement* renderer, RenderStyle* newStyle)
    641 {
    642     const RenderStyle& currentStyle = renderer->style();
    643 
    644     const PseudoStyleCache* pseudoStyleCache = currentStyle.cachedPseudoStyles();
    645     if (!pseudoStyleCache)
    646         return false;
    647 
    648     for (auto& cache : *pseudoStyleCache) {
    649         RefPtr<RenderStyle> newPseudoStyle;
    650         PseudoId pseudoId = cache->styleType();
    651         if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED)
    652             newPseudoStyle = renderer->uncachedFirstLineStyle(newStyle);
    653         else
    654             newPseudoStyle = renderer->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId), newStyle, newStyle);
    655         if (!newPseudoStyle)
    656             return true;
    657         if (*newPseudoStyle != *cache) {
    658             if (pseudoId < FIRST_INTERNAL_PSEUDOID)
    659                 newStyle->setHasPseudoStyle(pseudoId);
    660             newStyle->addCachedPseudoStyle(newPseudoStyle);
    661             if (pseudoId == FIRST_LINE || pseudoId == FIRST_LINE_INHERITED) {
    662                 // FIXME: We should do an actual diff to determine whether a repaint vs. layout
    663                 // is needed, but for now just assume a layout will be required. The diff code
    664                 // in RenderObject::setStyle would need to be factored out so that it could be reused.
    665                 renderer->setNeedsLayoutAndPrefWidthsRecalc();
    666             }
    667             return true;
    668         }
    669     }
    670     return false;
    671 }
    672 
    673 Change TreeResolver::resolveElement(Element& current)
    674 {
    675     Change localChange = Detach;
    676     RefPtr<RenderStyle> newStyle;
    677     RefPtr<RenderStyle> currentStyle = current.renderStyle();
    678 
    679     if (currentStyle && current.styleChangeType() != ReconstructRenderTree) {
    680         Ref<RenderStyle> style(styleForElement(current, parent().style));
    681         newStyle = style.ptr();
    682         localChange = determineChange(*currentStyle, style);
    683     }
    684     if (localChange == Detach) {
    685         if (current.renderer() || current.isNamedFlowContentNode())
    686             detachRenderTree(current, ReattachDetach);
    687 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
    688         else if (is<HTMLSlotElement>(current))
    689             detachRenderTree(current, ReattachDetach);
    690 #endif
    691         createRenderTreeRecursively(current, parent().style, parent().renderTreePosition, newStyle.release());
    692         invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(current);
    693 
    694         return Detach;
    695     }
    696 
    697     if (RenderElement* renderer = current.renderer()) {
    698         if (localChange != NoChange || pseudoStyleCacheIsInvalid(renderer, newStyle.get()) || (parent().change == Force && renderer->requiresForcedStyleRecalcPropagation()) || current.styleChangeType() == SyntheticStyleChange)
    699             renderer->setAnimatableStyle(*newStyle, current.styleChangeType() == SyntheticStyleChange ? StyleDifferenceRecompositeLayer : StyleDifferenceEqual);
    700     }
    701 
    702     // If "rem" units are used anywhere in the document, and if the document element's font size changes, then force font updating
    703     // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
    704     if (m_document.authorStyleSheets().usesRemUnits() && m_document.documentElement() == &current && localChange != NoChange && currentStyle && newStyle && currentStyle->fontSize() != newStyle->fontSize()) {
    705         // Cached RenderStyles may depend on the re units.
    706         scope().styleResolver.invalidateMatchedPropertiesCache();
    707         return Force;
    708     }
    709     if (parent().change == Force || current.styleChangeType() >= FullStyleChange)
    710         return Force;
    711 
    712     return localChange;
     388ElementUpdate TreeResolver::resolveElement(Element& element)
     389{
     390    auto newStyle = styleForElement(element, parent().style);
     391
     392    auto* renderer = element.renderer();
     393
     394    bool affectsRenderedSubtree = renderer || newStyle->display() != NONE || element.rendererIsNeeded(newStyle) || element.shouldMoveToFlowThread(newStyle);
     395    if (!affectsRenderedSubtree)
     396        return { };
     397
     398    ElementUpdate update;
     399
     400    bool needsNewRenderer = !renderer || element.styleChangeType() == ReconstructRenderTree || parent().change == Detach;
     401    if (!needsNewRenderer && m_document.frame()->animation().updateAnimations(*renderer, newStyle, newStyle))
     402        update.isSynthetic = true;
     403
     404    update.change = needsNewRenderer ? Detach : determineChange(renderer->style(), newStyle);
     405    update.style = WTFMove(newStyle);
     406
     407    if (element.styleChangeType() == SyntheticStyleChange)
     408        update.isSynthetic = true;
     409
     410    if (&element == m_document.documentElement()) {
     411        m_documentElementStyle = update.style;
     412
     413        // If "rem" units are used anywhere in the document, and if the document element's font size changes, then force font updating
     414        // all the way down the tree. This is simpler than having to maintain a cache of objects (and such font size changes should be rare anyway).
     415        if (m_document.authorStyleSheets().usesRemUnits() && update.change != NoChange && renderer && renderer->style().fontSize() != update.style->fontSize()) {
     416            // Cached RenderStyles may depend on the rem units.
     417            scope().styleResolver.invalidateMatchedPropertiesCache();
     418            update.change = Force;
     419        }
     420    }
     421
     422    // This is needed for resolving color:-webkit-text for subsequent elements.
     423    // FIXME: We shouldn't mutate document when resolving style.
     424    if (&element == m_document.body())
     425        m_document.setTextColor(update.style->visitedDependentColor(CSSPropertyColor));
     426
     427    if (update.change != Detach && (parent().change == Force || element.styleChangeType() >= FullStyleChange))
     428        update.change = Force;
     429
     430    return update;
    713431}
    714432
     
    730448    attachTextRenderer(text, renderTreePosition);
    731449    invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(text);
    732 }
    733 
    734 void TreeResolver::resolveBeforeOrAfterPseudoElement(Element& current, Change change, PseudoId pseudoId, RenderTreePosition& renderTreePosition)
    735 {
    736     if (!current.renderer())
    737         return;
    738     PseudoElement* existingPseudoElement = beforeOrAfterPseudoElement(current, pseudoId);
    739     if (!existingPseudoElement) {
    740         createRenderTreeForBeforeOrAfterPseudoElement(current, pseudoId, renderTreePosition);
    741         return;
    742     }
    743 
    744     if (existingPseudoElement->renderer())
    745         renderTreePosition.invalidateNextSibling(*existingPseudoElement->renderer());
    746 
    747     if (change == NoChange && !existingPseudoElement->needsStyleRecalc())
    748         return;
    749 
    750     if (needsPseudoElement(current, pseudoId)) {
    751         auto change = resolveElement(*existingPseudoElement);
    752         existingPseudoElement->didRecalcStyle(change);
    753         existingPseudoElement->clearNeedsStyleRecalc();
    754     } else
    755         clearBeforeOrAfterPseudoElement(current, pseudoId);
    756450}
    757451
     
    810504#endif // PLATFORM(IOS)
    811505
    812 void TreeResolver::pushParent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change)
     506void TreeResolver::pushParent(Element& element, ElementUpdate& update)
    813507{
    814508    scope().selectorFilter.pushParent(&element);
    815509
    816     Parent parent(element, style, renderTreePosition, change);
     510    Parent parent(element, update);
    817511
    818512    if (auto* shadowRoot = element.shadowRoot()) {
     
    828522
    829523    m_parentStack.append(WTFMove(parent));
    830 
    831     resolveBeforeOrAfterPseudoElement(element, change, BEFORE, renderTreePosition);
    832524}
    833525
     
    835527{
    836528    auto& parentElement = *parent().element;
    837 
    838     resolveBeforeOrAfterPseudoElement(parentElement, parent().change, AFTER, parent().renderTreePosition);
    839529
    840530    parentElement.clearNeedsStyleRecalc();
     
    856546    while (m_parentStack.size() > depth)
    857547        popParent();
     548}
     549
     550static bool shouldResolvePseudoElement(PseudoElement* pseudoElement)
     551{
     552    if (!pseudoElement)
     553        return false;
     554    bool needsStyleRecalc = pseudoElement->needsStyleRecalc();
     555    pseudoElement->clearNeedsStyleRecalc();
     556    return needsStyleRecalc;
    858557}
    859558
     
    879578        ASSERT(node.parentElement() == parent.element || is<ShadowRoot>(node.parentNode()) || node.parentElement()->shadowRoot());
    880579
    881         if (auto* existingRenderer = node.renderer())
    882             parent.renderTreePosition.invalidateNextSibling(*existingRenderer);
    883 
    884580        if (is<Text>(node)) {
    885             if (node.needsStyleRecalc())
    886                 resolveTextNode(downcast<Text>(node), parent.renderTreePosition);
     581            auto& text = downcast<Text>(node);
     582            if (text.styleChangeType() == ReconstructRenderTree && parent.change != Detach)
     583                m_update->addText(text, parent.element);
     584
     585            text.clearNeedsStyleRecalc();
    887586            it.traverseNextSkippingChildren();
    888587            continue;
     
    896595            parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle = element.affectsNextSiblingElementStyle();
    897596
    898         Change change = NoChange;
    899 
    900         bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || affectedByPreviousSibling;
     597        bool shouldResolveForPseudoElement = shouldResolvePseudoElement(element.beforePseudoElement()) || shouldResolvePseudoElement(element.afterPseudoElement());
     598
     599        ElementUpdate update;
     600        update.style = element.renderStyle();
     601
     602        bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || shouldResolveForPseudoElement || affectedByPreviousSibling;
    901603        if (shouldResolve) {
    902604#if PLATFORM(IOS)
     
    911613                }
    912614            }
    913             change = resolveElement(element);
     615
     616            update = resolveElement(element);
     617
     618            if (element.hasCustomStyleResolveCallbacks())
     619                element.didRecalcStyle(update.change);
     620
     621            if (affectedByPreviousSibling && update.change != Detach)
     622                update.change = Force;
     623
     624            if (update.style)
     625                m_update->addElement(element, parent.element, update);
    914626
    915627            element.clearNeedsStyleRecalc();
    916 
    917             if (element.hasCustomStyleResolveCallbacks())
    918                 element.didRecalcStyle(change);
    919 
    920             if (change == Detach) {
    921                 it.traverseNextSkippingChildren();
    922                 continue;
    923             }
    924 
    925             if (affectedByPreviousSibling)
    926                 change = Force;
    927         }
     628        }
     629
    928630
    929631#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
    930632        if (is<HTMLSlotElement>(element)) {
    931633            // FIXME: We should compute style for the slot and use it as parent style.
    932             // FIXME: This should be display:contents check.
    933             // Duplicate the style and render tree position from the current context.
    934             pushParent(element, parent.style.get(), parent.renderTreePosition, change);
     634            // Duplicate the style from the parent context.
     635            ElementUpdate slotUpdate;
     636            slotUpdate.style = parent.style.ptr();
     637            slotUpdate.change = update.change;
     638            if (!shouldResolve)
     639                m_update->addElement(element, parent.element, update);
     640            pushParent(element, slotUpdate);
    935641            it.traverseNext();
    936642            continue;
    937643        }
    938644#endif
    939         auto* renderer = element.renderer();
    940         if (!renderer) {
     645        if (!update.style) {
    941646            resetStyleForNonRenderedDescendants(element);
    942647            element.clearChildNeedsStyleRecalc();
    943648        }
    944649
    945         bool shouldIterateChildren = renderer && (element.childNeedsStyleRecalc() || change != NoChange);
     650        bool shouldIterateChildren = update.style && (element.childNeedsStyleRecalc() || update.change != NoChange);
    946651        if (!shouldIterateChildren) {
    947652            it.traverseNextSkippingChildren();
     
    949654        }
    950655
    951         pushParent(element, renderer->style(), RenderTreePosition(*renderer), change);
     656        pushParent(element, update);
    952657
    953658        it.traverseNext();
     
    957662}
    958663
    959 void TreeResolver::resolve(Change change)
     664std::unique_ptr<const Update> TreeResolver::resolve(Change change)
    960665{
    961666    auto& renderView = *m_document.renderView();
     
    963668    Element* documentElement = m_document.documentElement();
    964669    if (!documentElement)
    965         return;
     670        return nullptr;
    966671    if (change != Force && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
    967         return;
    968 
     672        return nullptr;
     673
     674    m_update = std::make_unique<Update>(m_document);
    969675    m_scopeStack.append(adoptRef(*new Scope(m_document)));
     676    m_parentStack.append(Parent(m_document, change));
    970677
    971678    // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
     
    973680    renderView.setUsesFirstLetterRules(renderView.usesFirstLetterRules() || scope().styleResolver.usesFirstLetterRules());
    974681
    975     m_parentStack.append(Parent(m_document, change));
    976 
    977682    resolveComposedTree();
    978683
     
    982687    m_parentStack.clear();
    983688    m_scopeStack.clear();
    984 }
    985 
    986 void detachRenderTree(Element& element)
    987 {
    988     detachRenderTree(element, NormalDetach);
     689
     690    if (m_update->roots().isEmpty())
     691        return { };
     692
     693    return WTFMove(m_update);
    989694}
    990695
  • trunk/Source/WebCore/style/StyleTreeResolver.h

    r198847 r198943  
    3333#include "StyleChange.h"
    3434#include "StyleSharingResolver.h"
     35#include "StyleUpdate.h"
    3536#include <functional>
     37#include <wtf/HashMap.h>
    3638#include <wtf/RefPtr.h>
    3739
     
    4850class StyleResolver;
    4951class Text;
     52class TreeChange;
    5053
    5154namespace Style {
     
    5457public:
    5558    TreeResolver(Document&);
     59    ~TreeResolver();
    5660
    57     void resolve(Change);
     61    std::unique_ptr<const Update> resolve(Change);
    5862
    5963private:
     
    6165
    6266    void resolveComposedTree();
    63     Change resolveElement(Element&);
    64     void resolveBeforeOrAfterPseudoElement(Element&, Change, PseudoId, RenderTreePosition&);
    65 
    66 
    67     void createRenderTreeRecursively(Element&, RenderStyle&, RenderTreePosition&, RefPtr<RenderStyle>&& resolvedStyle);
    68     void createRenderer(Element&, RenderTreePosition&, RefPtr<RenderStyle>&& resolvedStyle);
    69     void createRenderTreeForBeforeOrAfterPseudoElement(Element&, PseudoId, RenderTreePosition&);
    70     void createRenderTreeForChildren(ContainerNode&, RenderStyle&, RenderTreePosition&);
    71     void createRenderTreeForShadowRoot(ShadowRoot&);
    72 
    73 #if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
    74     void createRenderTreeForSlotAssignees(HTMLSlotElement&, RenderStyle& inheritedStyle, RenderTreePosition&);
    75 #endif
     67    ElementUpdate resolveElement(Element&);
    7668
    7769    struct Scope : RefCounted<Scope> {
     
    8981        Element* element;
    9082        Ref<RenderStyle> style;
    91         RenderTreePosition renderTreePosition;
    9283        Change change;
    9384        bool didPushScope { false };
     
    9586
    9687        Parent(Document&, Change);
    97         Parent(Element&, RenderStyle&, RenderTreePosition, Change);
     88        Parent(Element&, ElementUpdate&);
    9889    };
    9990
     
    10596    void popScope();
    10697
    107     void pushParent(Element&, RenderStyle&, RenderTreePosition, Change);
     98    void pushParent(Element&, ElementUpdate&);
    10899    void popParent();
    109100    void popParentsToDepth(unsigned depth);
    110101
    111102    Document& m_document;
     103    RefPtr<RenderStyle> m_documentElementStyle;
     104
    112105    Vector<Ref<Scope>, 4> m_scopeStack;
    113106    Vector<Parent, 32> m_parentStack;
     107
     108    std::unique_ptr<Update> m_update;
    114109};
    115110
    116 void detachRenderTree(Element&);
     111enum DetachType { NormalDetach, ReattachDetach };
     112void detachRenderTree(Element&, DetachType = NormalDetach);
    117113void detachTextRenderer(Text&);
    118114
  • trunk/Source/WebCore/svg/SVGElement.h

    r198847 r198943  
    184184    void updateRelativeLengthsInformation(bool hasRelativeLengths, SVGElement*);
    185185
     186    bool willRecalcStyle(Style::Change) override;
     187
    186188    class InstanceInvalidationGuard;
    187189
    188190private:
    189191    RenderStyle* computedStyle(PseudoId = NOPSEUDO) final;
    190     bool willRecalcStyle(Style::Change) override;
    191192
    192193    virtual bool isSupported(StringImpl* feature, StringImpl* version) const;
  • trunk/Source/WebCore/svg/SVGUseElement.cpp

    r198847 r198943  
    179179}
    180180
    181 void SVGUseElement::willAttachRenderers()
    182 {
     181bool SVGUseElement::willRecalcStyle(Style::Change change)
     182{
     183    // FIXME: Shadow tree should be updated before style recalc.
    183184    if (m_shadowTreeNeedsUpdate)
    184185        updateShadowTree();
    185     SVGGraphicsElement::willAttachRenderers();
     186    return SVGGraphicsElement::willRecalcStyle(change);
    186187}
    187188
  • trunk/Source/WebCore/svg/SVGUseElement.h

    r198847 r198943  
    6464    void parseAttribute(const QualifiedName&, const AtomicString&) override;
    6565    void svgAttributeChanged(const QualifiedName&) override;
    66     void willAttachRenderers() override;
     66    bool willRecalcStyle(Style::Change) override;
    6767    RenderPtr<RenderElement> createElementRenderer(Ref<RenderStyle>&&, const RenderTreePosition&) override;
    6868    void toClipPath(Path&) override;
Note: See TracChangeset for help on using the changeset viewer.