Changeset 198828 in webkit


Ignore:
Timestamp:
Mar 29, 2016 11:00:22 PM (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.

Switch 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
38 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r198819 r198828  
     12016-03-26  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-29  Nan Wang  <n_wang@apple.com>
    241
  • trunk/LayoutTests/TestExpectations

    r198665 r198828  
    989989webkit.org/b/155028 storage/indexeddb/modern/256-open-databases.html [ Skip ]
    990990
     991# Fixed by upcoming MathML refactoring
     992webkit.org/b/155019 mathml/presentation/menclose-notation-attribute-change-value.html [ Skip ]
     993
    991994### END OF IndexedDB failures
    992995########################################
  • trunk/LayoutTests/css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt

    r190658 r198828  
    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

    r169505 r198828  
    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

    r187932 r198828  
    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

    r187932 r198828  
    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

    r187932 r198828  
    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

    r187932 r198828  
    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

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

    r96257 r198828  
    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/platform/ios-simulator/TestExpectations

    r198789 r198828  
    20442044fast/regions/percentage-margins-rtl-variable-width-regions.html [ ImageOnlyFailure ]
    20452045fast/regions/percentage-margins-variable-width-regions.html [ ImageOnlyFailure ]
     2046fast/regions/position-writing-modes-in-variable-width-regions.html [ ImageOnlyFailure ]
    20462047fast/regions/positioning/fixed-in-named-flow-position-changed.html [ ImageOnlyFailure ]
    20472048fast/regions/positioning/fixed-inside-fixed-in-named-flow.html [ ImageOnlyFailure ]
  • trunk/LayoutTests/platform/mac-wk2/editing/mac/spelling/autocorrection-contraction-expected.txt

    r187932 r198828  
    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

    r177774 r198828  
    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

    r177774 r198828  
    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

    r180867 r198828  
    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

    r180867 r198828  
    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

    r177774 r198828  
    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/Source/WebCore/CMakeLists.txt

    r198811 r198828  
    26272627    style/InlineTextBoxStyle.cpp
    26282628    style/RenderTreePosition.cpp
     2629    style/RenderTreeUpdater.cpp
    26292630    style/StyleChange.cpp
    26302631    style/StyleFontSizeFunctions.cpp
     
    26332634    style/StyleSharingResolver.cpp
    26342635    style/StyleTreeResolver.cpp
     2636    style/StyleUpdate.cpp
    26352637
    26362638    svg/SVGAElement.cpp
  • trunk/Source/WebCore/ChangeLog

    r198819 r198828  
     12016-03-26  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            Switch willAttachRenderers to willRecalcStyle as the former is now called too late.
     213
     214        * svg/SVGUseElement.h:
     215
    12162016-03-29  Nan Wang  <n_wang@apple.com>
    2217
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r198762 r198828  
    65566556                E425A49A18292B840020CFCF /* CollectionIndexCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E425A49918292B840020CFCF /* CollectionIndexCache.h */; };
    65576557                E4295FA412B0614E00D1ACE0 /* ResourceLoadPriority.h in Headers */ = {isa = PBXBuildFile; fileRef = E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */; settings = {ATTRIBUTES = (Private, ); }; };
     6558                E42E76DA1C7AF76C00E3614D /* StyleUpdate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E42E76D91C7AF76C00E3614D /* StyleUpdate.cpp */; };
     6559                E42E76DC1C7AF77600E3614D /* StyleUpdate.h in Headers */ = {isa = PBXBuildFile; fileRef = E42E76DB1C7AF77600E3614D /* StyleUpdate.h */; };
    65586560                E43105B816750F0C00DB2FB8 /* NodeTraversal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */; };
    65596561                E43105BB16750F1600DB2FB8 /* NodeTraversal.h in Headers */ = {isa = PBXBuildFile; fileRef = E43105BA16750F1600DB2FB8 /* NodeTraversal.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    66116613                E453904D0EAFD637003695C8 /* WidgetIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = E453903C0EAFD637003695C8 /* WidgetIOS.mm */; };
    66126614                E45390AE0EAFF4B5003695C8 /* SystemMemoryIOS.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E45390AD0EAFF4B5003695C8 /* SystemMemoryIOS.cpp */; };
     6615                E46180291C8A06CD0026C02C /* RenderTreeUpdater.h in Headers */ = {isa = PBXBuildFile; fileRef = E46180281C8A06CD0026C02C /* RenderTreeUpdater.h */; };
     6616                E461802B1C8A06D90026C02C /* RenderTreeUpdater.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E461802A1C8A06D90026C02C /* RenderTreeUpdater.cpp */; };
    66136617                E461802D1C8DD2900026C02C /* StyleRelations.h in Headers */ = {isa = PBXBuildFile; fileRef = E461802C1C8DD2900026C02C /* StyleRelations.h */; };
    66146618                E461802F1C8DD4D20026C02C /* StyleRelations.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E461802E1C8DD4D20026C02C /* StyleRelations.cpp */; };
     
    1458814592                E425A49918292B840020CFCF /* CollectionIndexCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionIndexCache.h; sourceTree = "<group>"; };
    1458914593                E4295FA312B0614E00D1ACE0 /* ResourceLoadPriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadPriority.h; sourceTree = "<group>"; };
     14594                E42E76D91C7AF76C00E3614D /* StyleUpdate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleUpdate.cpp; sourceTree = "<group>"; };
     14595                E42E76DB1C7AF77600E3614D /* StyleUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleUpdate.h; sourceTree = "<group>"; };
    1459014596                E43105B716750F0C00DB2FB8 /* NodeTraversal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodeTraversal.cpp; sourceTree = "<group>"; };
    1459114597                E43105BA16750F1600DB2FB8 /* NodeTraversal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeTraversal.h; sourceTree = "<group>"; };
     
    1463514641                E453903C0EAFD637003695C8 /* WidgetIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WidgetIOS.mm; sourceTree = "<group>"; };
    1463614642                E45390AD0EAFF4B5003695C8 /* SystemMemoryIOS.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SystemMemoryIOS.cpp; sourceTree = "<group>"; };
     14643                E46180281C8A06CD0026C02C /* RenderTreeUpdater.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeUpdater.h; sourceTree = "<group>"; };
     14644                E461802A1C8A06D90026C02C /* RenderTreeUpdater.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeUpdater.cpp; sourceTree = "<group>"; };
    1463714645                E461802C1C8DD2900026C02C /* StyleRelations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleRelations.h; sourceTree = "<group>"; };
    1463814646                E461802E1C8DD4D20026C02C /* StyleRelations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StyleRelations.cpp; sourceTree = "<group>"; };
     
    2350123509                                5824ABA81AE849C8009074B7 /* RenderTreePosition.cpp */,
    2350223510                                5824ABA91AE849C8009074B7 /* RenderTreePosition.h */,
     23511                                E461802A1C8A06D90026C02C /* RenderTreeUpdater.cpp */,
     23512                                E46180281C8A06CD0026C02C /* RenderTreeUpdater.h */,
    2350323513                                E401E0A51C3C0CF700F34D10 /* StyleChange.cpp */,
    2350423514                                E401E0A31C3C0B8300F34D10 /* StyleChange.h */,
     
    2351323523                                E4DEAA1517A93DC3000E0430 /* StyleTreeResolver.cpp */,
    2351423524                                E4DEAA1617A93DC3000E0430 /* StyleTreeResolver.h */,
     23525                                E42E76D91C7AF76C00E3614D /* StyleUpdate.cpp */,
     23526                                E42E76DB1C7AF77600E3614D /* StyleUpdate.h */,
    2351523527                        );
    2351623528                        path = style;
     
    2594825960                                7728694F14F8882500F484DC /* EXTTextureFilterAnisotropic.h in Headers */,
    2594925961                                A75E8B890E1DE2D6007F2481 /* FEBlend.h in Headers */,
     25962                                E46180291C8A06CD0026C02C /* RenderTreeUpdater.h in Headers */,
    2595025963                                A75E8B8B0E1DE2D6007F2481 /* FEColorMatrix.h in Headers */,
    2595125964                                A75E8B8D0E1DE2D6007F2481 /* FEComponentTransfer.h in Headers */,
     
    2613926152                                93F198E508245E59001E9ABC /* HTMLDocument.h in Headers */,
    2614026153                                977B3867122883E900B81FF8 /* HTMLDocumentParser.h in Headers */,
     26154                                E42E76DC1C7AF77600E3614D /* StyleUpdate.h in Headers */,
    2614126155                                93309DE8099E64920056E581 /* htmlediting.h in Headers */,
    2614226156                                93F198E608245E59001E9ABC /* HTMLElement.h in Headers */,
     
    3052430538                                E1FF8F64180745D800132674 /* JSSubtleCrypto.cpp in Sources */,
    3052530539                                E1FF8F681807460800132674 /* JSSubtleCryptoCustom.cpp in Sources */,
     30540                                E461802B1C8A06D90026C02C /* RenderTreeUpdater.cpp in Sources */,
    3052630541                                B20111070AB7740500DB0E68 /* JSSVGAElement.cpp in Sources */,
    3052730542                                24D9129113CA951E00D21915 /* JSSVGAltGlyphDefElement.cpp in Sources */,
     
    3106231077                                FD581FB41520F93B003A7A75 /* PeriodicWave.cpp in Sources */,
    3106331078                                49D5DC2D0F423A73008F20FD /* PerspectiveTransformOperation.cpp in Sources */,
     31079                                E42E76DA1C7AF76C00E3614D /* StyleUpdate.cpp in Sources */,
    3106431080                                D0FF2A5D11F8C45A007E74E0 /* PingLoader.cpp in Sources */,
    3106531081                                CD7D33431C7A123F00041293 /* PixelBufferConformerCV.cpp in Sources */,
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r198255 r198828  
    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

    r197764 r198828  
    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

    r198658 r198828  
    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

    r198658 r198828  
    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

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

    r197887 r198828  
    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

    r198568 r198828  
    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

    r198701 r198828  
    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

    r191112 r198828  
    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

    r197764 r198828  
    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

    r197764 r198828  
    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

    r198584 r198828  
    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

    r198584 r198828  
    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

    r198584 r198828  
    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
     
    132119    : element(nullptr)
    133120    , style(*document.renderStyle())
    134     , renderTreePosition(*document.renderView())
    135121    , change(change)
    136122{
    137123}
    138124
    139 TreeResolver::Parent::Parent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change)
     125TreeResolver::Parent::Parent(Element& element, ElementUpdate& update)
    140126    : element(&element)
    141     , style(style)
    142     , renderTreePosition(renderTreePosition)
    143     , change(change)
     127    , style(*update.style)
     128    , change(update.change)
    144129{
    145130}
     
    159144{
    160145    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;
    172146}
    173147
     
    179153    }
    180154
     155    scope().styleResolver.setOverrideDocumentElementStyle(m_documentElementStyle.get());
     156
    181157    if (element.hasCustomStyleResolveCallbacks()) {
    182         RenderStyle* shadowHostStyle = scope().shadowRoot ? scope().shadowRoot->host()->renderStyle() : nullptr;
     158        RenderStyle* shadowHostStyle = scope().shadowRoot ? m_update->elementStyle(*scope().shadowRoot->host()) : nullptr;
    183159        if (auto customStyle = element.resolveCustomStyle(inheritedStyle, shadowHostStyle)) {
    184             Style::commitRelationsToDocument(WTFMove(customStyle->relations));
     160            if (customStyle->relations)
     161                commitRelations(WTFMove(customStyle->relations), *m_update);
     162
    185163            return WTFMove(customStyle->renderStyle);
    186164        }
    187165    }
    188166
    189     if (auto style = scope().sharingResolver.resolve(element))
     167    if (auto style = scope().sharingResolver.resolve(element, *m_update))
    190168        return *style;
    191169
    192170    auto elementStyle = scope().styleResolver.styleForElement(element, &inheritedStyle, MatchAllRules, nullptr, &scope().selectorFilter);
    193171
    194     Style::commitRelationsToDocument(WTFMove(elementStyle.relations));
     172    if (elementStyle.relations)
     173        commitRelations(WTFMove(elementStyle.relations), *m_update);
     174
    195175    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);
    262176}
    263177
     
    349263
    350264    textNode.setRenderer(newRenderer.get());
    351     // Parent takes care of the animations, no need to call setAnimatableStyle.
    352265    renderTreePosition.insert(*newRenderer.leakPtr());
    353266}
     
    382295}
    383296
    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 
    446297static void resetStyleForNonRenderedDescendants(Element& current)
    447298{
    448299    // FIXME: This is not correct with shadow trees. This should be done with ComposedTreeIterator.
    449     ASSERT(!current.renderer());
    450300    bool elementNeedingStyleRecalcAffectsNextSiblingElementStyle = false;
    451301    for (auto& child : childrenOfType<Element>(current)) {
    452         ASSERT(!child.renderer());
    453302        bool affectedByPreviousSibling = child.styleIsAffectedByPreviousSibling() && elementNeedingStyleRecalcAffectsNextSiblingElementStyle;
    454303        if (child.needsStyleRecalc() || elementNeedingStyleRecalcAffectsNextSiblingElementStyle)
     
    465314        }
    466315    }
    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();
    572316}
    573317
     
    607351#endif
    608352
    609 static void detachRenderTree(Element& current, DetachType detachType)
     353void detachRenderTree(Element& current, DetachType detachType)
    610354{
    611355    WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
     
    638382}
    639383
    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;
     384ElementUpdate TreeResolver::resolveElement(Element& element)
     385{
     386    ElementUpdate update;
     387
     388    auto newStyle = styleForElement(element, parent().style);
     389
     390    auto* renderer = element.renderer();
     391    bool needsNewRenderer = !renderer || element.styleChangeType() == ReconstructRenderTree || parent().change == Detach;
     392
     393    if (!needsNewRenderer && m_document.frame()->animation().updateAnimations(*renderer, newStyle, newStyle))
     394        update.isSynthetic = true;
     395
     396    update.change = needsNewRenderer ? Detach : determineChange(renderer->style(), newStyle);
     397    update.style = WTFMove(newStyle);
     398
     399    if (element.styleChangeType() == SyntheticStyleChange)
     400        update.isSynthetic = true;
     401
     402    if (&element == m_document.documentElement()) {
     403        m_documentElementStyle = update.style;
     404
     405        // If "rem" units are used anywhere in the document, and if the document element's font size changes, then force font updating
     406        // 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).
     407        if (m_document.authorStyleSheets().usesRemUnits() && update.change != NoChange && renderer && update.style && renderer->style().fontSize() != update.style->fontSize()) {
     408            // Cached RenderStyles may depend on the rem units.
     409            scope().styleResolver.invalidateMatchedPropertiesCache();
     410            update.change = Force;
     411        }
     412    }
     413
     414    // This is needed for resolving color:-webkit-text for subsequent elements.
     415    // FIXME: We shouldn't mutate document when resolving style.
     416    if (&element == m_document.body())
     417        m_document.setTextColor(update.style->visitedDependentColor(CSSPropertyColor));
     418
     419    if (update.change != Detach && (parent().change == Force || element.styleChangeType() >= FullStyleChange))
     420        update.change = Force;
     421
     422    return update;
    713423}
    714424
     
    730440    attachTextRenderer(text, renderTreePosition);
    731441    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);
    756442}
    757443
     
    810496#endif // PLATFORM(IOS)
    811497
    812 void TreeResolver::pushParent(Element& element, RenderStyle& style, RenderTreePosition renderTreePosition, Change change)
     498void TreeResolver::pushParent(Element& element, ElementUpdate& update)
    813499{
    814500    scope().selectorFilter.pushParent(&element);
    815501
    816     Parent parent(element, style, renderTreePosition, change);
     502    Parent parent(element, update);
    817503
    818504    if (auto* shadowRoot = element.shadowRoot()) {
     
    828514
    829515    m_parentStack.append(WTFMove(parent));
    830 
    831     resolveBeforeOrAfterPseudoElement(element, change, BEFORE, renderTreePosition);
    832516}
    833517
     
    835519{
    836520    auto& parentElement = *parent().element;
    837 
    838     resolveBeforeOrAfterPseudoElement(parentElement, parent().change, AFTER, parent().renderTreePosition);
    839521
    840522    parentElement.clearNeedsStyleRecalc();
     
    856538    while (m_parentStack.size() > depth)
    857539        popParent();
     540}
     541
     542static bool shouldResolvePseudoElement(PseudoElement* pseudoElement)
     543{
     544    if (!pseudoElement)
     545        return false;
     546    bool needsStyleRecalc = pseudoElement->needsStyleRecalc();
     547    pseudoElement->clearNeedsStyleRecalc();
     548    return needsStyleRecalc;
    858549}
    859550
     
    879570        ASSERT(node.parentElement() == parent.element || is<ShadowRoot>(node.parentNode()) || node.parentElement()->shadowRoot());
    880571
    881         if (auto* existingRenderer = node.renderer())
    882             parent.renderTreePosition.invalidateNextSibling(*existingRenderer);
    883 
    884572        if (is<Text>(node)) {
    885             if (node.needsStyleRecalc())
    886                 resolveTextNode(downcast<Text>(node), parent.renderTreePosition);
     573            auto& text = downcast<Text>(node);
     574            if (text.styleChangeType() == ReconstructRenderTree && parent.change != Detach)
     575                m_update->addText(text, parent.element);
     576
     577            text.clearNeedsStyleRecalc();
    887578            it.traverseNextSkippingChildren();
    888579            continue;
     
    896587            parent.elementNeedingStyleRecalcAffectsNextSiblingElementStyle = element.affectsNextSiblingElementStyle();
    897588
    898         Change change = NoChange;
    899 
    900         bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || affectedByPreviousSibling;
     589        bool shouldResolveForPseudoElement = shouldResolvePseudoElement(element.beforePseudoElement()) || shouldResolvePseudoElement(element.afterPseudoElement());
     590
     591        ElementUpdate update;
     592        update.style = element.renderStyle();
     593
     594        bool shouldResolve = parent.change >= Inherit || element.needsStyleRecalc() || shouldResolveForPseudoElement || affectedByPreviousSibling;
    901595        if (shouldResolve) {
    902596#if PLATFORM(IOS)
     
    911605                }
    912606            }
    913             change = resolveElement(element);
     607            update = resolveElement(element);
     608
     609            if (element.hasCustomStyleResolveCallbacks())
     610                element.didRecalcStyle(update.change);
     611
     612            if (affectedByPreviousSibling && update.change != Detach)
     613                update.change = Force;
     614
     615            m_update->addElement(element, parent.element, update);
    914616
    915617            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         }
     618        }
     619
    928620
    929621#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
    930622        if (is<HTMLSlotElement>(element)) {
    931623            // 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);
     624            // Duplicate the style from the parent context.
     625            ElementUpdate slotUpdate;
     626            slotUpdate.style = parent.style.ptr();
     627            slotUpdate.change = update.change;
     628            if (!shouldResolve)
     629                m_update->addElement(element, parent.element, update);
     630            pushParent(element, slotUpdate);
    935631            it.traverseNext();
    936632            continue;
    937633        }
    938634#endif
    939         auto* renderer = element.renderer();
    940         if (!renderer) {
     635        if (!update.style) {
    941636            resetStyleForNonRenderedDescendants(element);
    942637            element.clearChildNeedsStyleRecalc();
    943638        }
    944639
    945         bool shouldIterateChildren = renderer && (element.childNeedsStyleRecalc() || change != NoChange);
     640        bool shouldIterateChildren = update.style && (element.childNeedsStyleRecalc() || update.change != NoChange);
    946641        if (!shouldIterateChildren) {
    947642            it.traverseNextSkippingChildren();
     
    949644        }
    950645
    951         pushParent(element, renderer->style(), RenderTreePosition(*renderer), change);
     646        pushParent(element, update);
    952647
    953648        it.traverseNext();
     
    957652}
    958653
    959 void TreeResolver::resolve(Change change)
     654std::unique_ptr<const Update> TreeResolver::resolve(Change change)
    960655{
    961656    auto& renderView = *m_document.renderView();
     
    963658    Element* documentElement = m_document.documentElement();
    964659    if (!documentElement)
    965         return;
     660        return nullptr;
    966661    if (change != Force && !documentElement->childNeedsStyleRecalc() && !documentElement->needsStyleRecalc())
    967         return;
    968 
     662        return nullptr;
     663
     664    m_update = std::make_unique<Update>(m_document);
    969665    m_scopeStack.append(adoptRef(*new Scope(m_document)));
     666    m_parentStack.append(Parent(m_document, change));
    970667
    971668    // Pseudo element removal and similar may only work with these flags still set. Reset them after the style recalc.
     
    973670    renderView.setUsesFirstLetterRules(renderView.usesFirstLetterRules() || scope().styleResolver.usesFirstLetterRules());
    974671
    975     m_parentStack.append(Parent(m_document, change));
    976 
    977672    resolveComposedTree();
    978673
     
    982677    m_parentStack.clear();
    983678    m_scopeStack.clear();
    984 }
    985 
    986 void detachRenderTree(Element& element)
    987 {
    988     detachRenderTree(element, NormalDetach);
     679
     680    if (m_update->roots().isEmpty())
     681        return nullptr;
     682
     683    return WTFMove(m_update);
    989684}
    990685
  • trunk/Source/WebCore/style/StyleTreeResolver.h

    r197764 r198828  
    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 {
     
    5558    TreeResolver(Document&);
    5659
    57     void resolve(Change);
     60    std::unique_ptr<const Update> resolve(Change);
    5861
    5962private:
     
    6164
    6265    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
     66    ElementUpdate resolveElement(Element&);
    7667
    7768    struct Scope : RefCounted<Scope> {
     
    8980        Element* element;
    9081        Ref<RenderStyle> style;
    91         RenderTreePosition renderTreePosition;
    9282        Change change;
    9383        bool didPushScope { false };
     
    9585
    9686        Parent(Document&, Change);
    97         Parent(Element&, RenderStyle&, RenderTreePosition, Change);
     87        Parent(Element&, ElementUpdate&);
    9888    };
    9989
     
    10595    void popScope();
    10696
    107     void pushParent(Element&, RenderStyle&, RenderTreePosition, Change);
     97    void pushParent(Element&, ElementUpdate&);
    10898    void popParent();
    10999    void popParentsToDepth(unsigned depth);
    110100
    111101    Document& m_document;
     102    RefPtr<RenderStyle> m_documentElementStyle;
     103
    112104    Vector<Ref<Scope>, 4> m_scopeStack;
    113105    Vector<Parent, 32> m_parentStack;
     106
     107    std::unique_ptr<Update> m_update;
    114108};
    115109
    116 void detachRenderTree(Element&);
     110enum DetachType { NormalDetach, ReattachDetach };
     111void detachRenderTree(Element&, DetachType = NormalDetach);
    117112void detachTextRenderer(Text&);
    118113
  • trunk/Source/WebCore/svg/SVGElement.h

    r197764 r198828  
    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

    r197194 r198828  
    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

    r197563 r198828  
    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.