Changeset 223500 in webkit


Ignore:
Timestamp:
Oct 17, 2017 2:21:05 AM (6 years ago)
Author:
Antti Koivisto
Message:

Resolve ::before and ::after pseudo elements during style resolution
https://bugs.webkit.org/show_bug.cgi?id=178339

Reviewed by Ryosuke Niwa.

They are currently resolved during render tree building which creates problems with display:contents and animations.

  • dom/PseudoElement.cpp:

(WebCore::PseudoElement::PseudoElement):

Call InspectorInstrumentation from constructor.

  • style/RenderTreeUpdater.cpp:

(WebCore::RenderTreeUpdater::Parent::Parent):
(WebCore::RenderTreeUpdater::updateRenderTree):
(WebCore::RenderTreeUpdater::pushParent):

Push the full update to the parent stack.

(WebCore::RenderTreeUpdater::popParent):
(WebCore::RenderTreeUpdater::updateBeforeDescendants):
(WebCore::RenderTreeUpdater::updateAfterDescendants):
(WebCore::RenderTreeUpdater::invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded):

  • style/RenderTreeUpdater.h:
  • style/RenderTreeUpdaterGeneratedContent.cpp:

(WebCore::RenderTreeUpdater::GeneratedContent::updatePseudoElement):

No need to resolve pseudo style, we have it already.

(WebCore::RenderTreeUpdater::GeneratedContent::needsPseudoElement):
(WebCore::RenderTreeUpdater::GeneratedContent::updateBeforePseudoElement): Deleted.
(WebCore::RenderTreeUpdater::GeneratedContent::updateAfterPseudoElement): Deleted.

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

(WebCore::Style::TreeResolver::resolveElement):
(WebCore::Style::TreeResolver::resolvePseudoStyle):

Resolve pseudos.

(WebCore::Style::TreeResolver::createAnimatedElementUpdate):

Make a private member function.

(WebCore::Style::TreeResolver::resolveComposedTree):

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

(WebCore::Style::Update::elementUpdates const):
(WebCore::Style::Update::elementUpdates):

Bundle the style update for an element and the associated before/after pseudos.

(WebCore::Style::Update::elementStyle const):
(WebCore::Style::Update::elementStyle):
(WebCore::Style::Update::addElement):
(WebCore::Style::Update::elementUpdate const): Deleted.
(WebCore::Style::Update::elementUpdate): Deleted.

  • style/StyleUpdate.h:
Location:
trunk/Source/WebCore
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r223476 r223500  
     12017-10-17  Antti Koivisto  <antti@apple.com>
     2
     3        Resolve ::before and ::after pseudo elements during style resolution
     4        https://bugs.webkit.org/show_bug.cgi?id=178339
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        They are currently resolved during render tree building which creates problems with display:contents and animations.
     9
     10        * dom/PseudoElement.cpp:
     11        (WebCore::PseudoElement::PseudoElement):
     12
     13            Call InspectorInstrumentation from constructor.
     14
     15        * style/RenderTreeUpdater.cpp:
     16        (WebCore::RenderTreeUpdater::Parent::Parent):
     17        (WebCore::RenderTreeUpdater::updateRenderTree):
     18        (WebCore::RenderTreeUpdater::pushParent):
     19
     20            Push the full update to the parent stack.
     21
     22        (WebCore::RenderTreeUpdater::popParent):
     23        (WebCore::RenderTreeUpdater::updateBeforeDescendants):
     24        (WebCore::RenderTreeUpdater::updateAfterDescendants):
     25        (WebCore::RenderTreeUpdater::invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded):
     26        * style/RenderTreeUpdater.h:
     27        * style/RenderTreeUpdaterGeneratedContent.cpp:
     28        (WebCore::RenderTreeUpdater::GeneratedContent::updatePseudoElement):
     29
     30            No need to resolve pseudo style, we have it already.
     31
     32        (WebCore::RenderTreeUpdater::GeneratedContent::needsPseudoElement):
     33        (WebCore::RenderTreeUpdater::GeneratedContent::updateBeforePseudoElement): Deleted.
     34        (WebCore::RenderTreeUpdater::GeneratedContent::updateAfterPseudoElement): Deleted.
     35        * style/RenderTreeUpdaterGeneratedContent.h:
     36        * style/StyleTreeResolver.cpp:
     37        (WebCore::Style::TreeResolver::resolveElement):
     38        (WebCore::Style::TreeResolver::resolvePseudoStyle):
     39
     40            Resolve pseudos.
     41
     42        (WebCore::Style::TreeResolver::createAnimatedElementUpdate):
     43
     44            Make a private member function.
     45
     46        (WebCore::Style::TreeResolver::resolveComposedTree):
     47        * style/StyleTreeResolver.h:
     48        * style/StyleUpdate.cpp:
     49        (WebCore::Style::Update::elementUpdates const):
     50        (WebCore::Style::Update::elementUpdates):
     51
     52            Bundle the style update for an element and the associated before/after pseudos.
     53
     54        (WebCore::Style::Update::elementStyle const):
     55        (WebCore::Style::Update::elementStyle):
     56        (WebCore::Style::Update::addElement):
     57        (WebCore::Style::Update::elementUpdate const): Deleted.
     58        (WebCore::Style::Update::elementUpdate): Deleted.
     59        * style/StyleUpdate.h:
     60
    1612017-10-17  Keith Miller  <keith_miller@apple.com>
    262
  • trunk/Source/WebCore/dom/PseudoElement.cpp

    r220956 r223500  
    2929#include "PseudoElement.h"
    3030
     31#include "CSSAnimationController.h"
    3132#include "ContentData.h"
    3233#include "InspectorInstrumentation.h"
     
    7273}
    7374
     75Ref<PseudoElement> PseudoElement::create(Element& host, PseudoId pseudoId)
     76{
     77    auto pseudoElement = adoptRef(*new PseudoElement(host, pseudoId));
     78
     79    InspectorInstrumentation::pseudoElementCreated(host.document().page(), pseudoElement.get());
     80
     81    return pseudoElement;
     82}
     83
    7484void PseudoElement::clearHostElement()
    7585{
    7686    InspectorInstrumentation::pseudoElementDestroyed(document().page(), *this);
     87
     88    if (auto* frame = document().frame())
     89        frame->animation().cancelAnimations(*this);
    7790
    7891    m_hostElement = nullptr;
  • trunk/Source/WebCore/dom/PseudoElement.h

    r222259 r223500  
    3434class PseudoElement final : public Element {
    3535public:
    36     static Ref<PseudoElement> create(Element& host, PseudoId pseudoId)
    37     {
    38         return adoptRef(*new PseudoElement(host, pseudoId));
    39     }
     36    static Ref<PseudoElement> create(Element& host, PseudoId);
    4037    virtual ~PseudoElement();
    4138
  • trunk/Source/WebCore/style/RenderTreeUpdater.cpp

    r223131 r223500  
    7575}
    7676
    77 RenderTreeUpdater::Parent::Parent(Element& element, Style::Change styleChange)
     77RenderTreeUpdater::Parent::Parent(Element& element, const Style::ElementUpdates* updates)
    7878    : element(&element)
    79     , styleChange(styleChange)
     79    , updates(updates)
    8080    , renderTreePosition(element.renderer() ? std::make_optional(RenderTreePosition(*element.renderer())) : std::nullopt)
    8181{
     
    176176            auto& text = downcast<Text>(node);
    177177            auto* textUpdate = m_styleUpdate->textUpdate(text);
    178             if (parent().styleChange == Style::Detach || textUpdate || m_invalidatedWhitespaceOnlyTextSiblings.contains(&text))
     178            if ((parent().updates && parent().updates->update.change == Style::Detach) || textUpdate || m_invalidatedWhitespaceOnlyTextSiblings.contains(&text))
    179179                updateTextRenderer(text, textUpdate);
    180180
     
    185185        auto& element = downcast<Element>(node);
    186186
    187         auto* elementUpdate = m_styleUpdate->elementUpdate(element);
     187        auto* elementUpdates = m_styleUpdate->elementUpdates(element);
    188188
    189189        // We hop through display: contents elements in findRenderingRoot, so
    190190        // there may be other updates down the tree.
    191         if (!elementUpdate && !element.hasDisplayContents()) {
     191        if (!elementUpdates && !element.hasDisplayContents()) {
    192192            it.traverseNextSkippingChildren();
    193193            continue;
    194194        }
    195195
    196         if (elementUpdate)
    197             updateElementRenderer(element, *elementUpdate);
     196        if (elementUpdates)
     197            updateElementRenderer(element, elementUpdates->update);
    198198
    199199        bool mayHaveRenderedDescendants = element.renderer() || (element.hasDisplayContents() && shouldCreateRenderer(element, renderTreePosition().parent()));
     
    203203        }
    204204
    205         pushParent(element, elementUpdate ? elementUpdate->change : Style::NoChange);
     205        pushParent(element, elementUpdates);
    206206
    207207        it.traverseNext();
     
    223223}
    224224
    225 void RenderTreeUpdater::pushParent(Element& element, Style::Change changeType)
    226 {
    227     m_parentStack.append(Parent(element, changeType));
    228 
    229     updateBeforeDescendants(element);
     225void RenderTreeUpdater::pushParent(Element& element, const Style::ElementUpdates* updates)
     226{
     227    m_parentStack.append(Parent(element, updates));
     228
     229    updateBeforeDescendants(element, updates);
    230230}
    231231
     
    234234    auto& parent = m_parentStack.last();
    235235    if (parent.element)
    236         updateAfterDescendants(*parent.element, parent.styleChange);
     236        updateAfterDescendants(*parent.element, parent.updates);
    237237
    238238    m_parentStack.removeLast();
     
    247247}
    248248
    249 void RenderTreeUpdater::updateBeforeDescendants(Element& element)
    250 {
    251     generatedContent().updateBeforePseudoElement(element);
    252 }
    253 
    254 void RenderTreeUpdater::updateAfterDescendants(Element& element, Style::Change styleChange)
    255 {
    256     generatedContent().updateAfterPseudoElement(element);
     249void RenderTreeUpdater::updateBeforeDescendants(Element& element, const Style::ElementUpdates* updates)
     250{
     251    if (updates)
     252        generatedContent().updatePseudoElement(element, updates->beforePseudoElementUpdate, BEFORE);
     253}
     254
     255void RenderTreeUpdater::updateAfterDescendants(Element& element, const Style::ElementUpdates* updates)
     256{
     257    if (updates)
     258        generatedContent().updatePseudoElement(element, updates->afterPseudoElementUpdate, AFTER);
    257259
    258260    auto* renderer = element.renderer();
     
    268270        MultiColumn::update(downcast<RenderBlockFlow>(*renderer));
    269271
    270     if (element.hasCustomStyleResolveCallbacks() && styleChange == Style::Detach)
     272    if (element.hasCustomStyleResolveCallbacks() && updates && updates->update.change == Style::Detach)
    271273        element.didAttachRenderers();
    272274}
     
    471473    for (Node* sibling = current.nextSibling(); sibling; sibling = sibling->nextSibling()) {
    472474        if (is<Element>(*sibling)) {
    473             if (m_styleUpdate->elementUpdate(downcast<Element>(*sibling)))
     475            if (m_styleUpdate->elementUpdates(downcast<Element>(*sibling)))
    474476                return;
    475477            // Text renderers beyond rendered elements can't be affected.
  • trunk/Source/WebCore/style/RenderTreeUpdater.h

    r222129 r223500  
    6363    void createRenderer(Element&, RenderStyle&&);
    6464    void invalidateWhitespaceOnlyTextSiblingsAfterAttachIfNeeded(Node&);
    65     void updateBeforeDescendants(Element&);
    66     void updateAfterDescendants(Element&, Style::Change);
     65    void updateBeforeDescendants(Element&, const Style::ElementUpdates*);
     66    void updateAfterDescendants(Element&, const Style::ElementUpdates*);
    6767
    6868    struct Parent {
    6969        Element* element { nullptr };
    70         Style::Change styleChange { Style::NoChange };
     70        const Style::ElementUpdates* updates { nullptr };
    7171        std::optional<RenderTreePosition> renderTreePosition;
    7272
    7373        Parent(ContainerNode& root);
    74         Parent(Element&, Style::Change);
     74        Parent(Element&, const Style::ElementUpdates*);
    7575    };
    7676    Parent& parent() { return m_parentStack.last(); }
     
    7979    GeneratedContent& generatedContent() { return *m_generatedContent; }
    8080
    81     void pushParent(Element&, Style::Change);
     81    void pushParent(Element&, const Style::ElementUpdates*);
    8282    void popParent();
    8383    void popParentsToDepth(unsigned depth);
  • trunk/Source/WebCore/style/RenderTreeUpdaterGeneratedContent.cpp

    r222679 r223500  
    4343    : m_updater(updater)
    4444{
    45 }
    46 
    47 void RenderTreeUpdater::GeneratedContent::updateBeforePseudoElement(Element& element)
    48 {
    49     updatePseudoElement(element, BEFORE);
    50 }
    51 
    52 void RenderTreeUpdater::GeneratedContent::updateAfterPseudoElement(Element& element)
    53 {
    54     updatePseudoElement(element, AFTER);
    5545}
    5646
     
    10393}
    10494
    105 void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, PseudoId pseudoId)
     95void RenderTreeUpdater::GeneratedContent::updatePseudoElement(Element& current, const std::optional<Style::ElementUpdate>& update, PseudoId pseudoId)
    10696{
    10797    PseudoElement* pseudoElement = pseudoId == BEFORE ? current.beforePseudoElement() : current.afterPseudoElement();
     
    110100        m_updater.renderTreePosition().invalidateNextSibling(*renderer);
    111101
    112     if (!needsPseudoElement(current, pseudoId)) {
     102    if (!needsPseudoElement(current, update)) {
    113103        if (pseudoElement) {
    114104            if (pseudoId == BEFORE)
     
    126116    }
    127117
    128     auto newStyle = RenderStyle::clonePtr(*current.renderer()->getCachedPseudoStyle(pseudoId, &current.renderer()->style()));
    129 
    130     auto elementUpdate = Style::TreeResolver::createAnimatedElementUpdate(WTFMove(newStyle), *pseudoElement, Style::NoChange);
    131 
    132     if (elementUpdate.change == Style::NoChange)
     118    if (update->change == Style::NoChange)
    133119        return;
    134120
    135121    if (newPseudoElement) {
    136         InspectorInstrumentation::pseudoElementCreated(m_updater.m_document.page(), *newPseudoElement);
    137122        if (pseudoId == BEFORE)
    138123            current.setBeforePseudoElement(newPseudoElement.releaseNonNull());
     
    141126    }
    142127
    143     m_updater.updateElementRenderer(*pseudoElement, elementUpdate);
     128    m_updater.updateElementRenderer(*pseudoElement, *update);
    144129
    145130    auto* pseudoRenderer = pseudoElement->renderer();
     
    147132        return;
    148133
    149     if (elementUpdate.change == Style::Detach)
     134    if (update->change == Style::Detach)
    150135        createContentRenderers(*pseudoRenderer);
    151136    else
     
    160145}
    161146
    162 bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(Element& current, PseudoId pseudoId)
     147bool RenderTreeUpdater::GeneratedContent::needsPseudoElement(Element& current, const std::optional<Style::ElementUpdate>& update)
    163148{
     149    ASSERT(!current.isPseudoElement());
     150    if (!update)
     151        return false;
    164152    if (!current.renderer() || !current.renderer()->canHaveGeneratedChildren())
    165153        return false;
    166     if (current.isPseudoElement())
    167         return false;
    168     if (!pseudoElementRendererIsNeeded(current.renderer()->getCachedPseudoStyle(pseudoId)))
     154    if (!pseudoElementRendererIsNeeded(update->style.get()))
    169155        return false;
    170156    return true;
  • trunk/Source/WebCore/style/RenderTreeUpdaterGeneratedContent.h

    r220956 r223500  
    3838    GeneratedContent(RenderTreeUpdater&);
    3939
    40     void updateBeforePseudoElement(Element&);
    41     void updateAfterPseudoElement(Element&);
     40    void updatePseudoElement(Element&, const std::optional<Style::ElementUpdate>&, PseudoId);
    4241    void updateRemainingQuotes();
    4342
    4443private:
    45     void updatePseudoElement(Element&, PseudoId);
    4644    void updateQuotesUpTo(RenderQuote*);
    4745   
    48     static bool needsPseudoElement(Element&, PseudoId);
     46    static bool needsPseudoElement(Element&, const std::optional<Style::ElementUpdate>&);
    4947
    5048    RenderTreeUpdater& m_updater;
  • trunk/Source/WebCore/style/StyleTreeResolver.cpp

    r222806 r223500  
    175175}
    176176
    177 ElementUpdate TreeResolver::resolveElement(Element& element)
     177ElementUpdates TreeResolver::resolveElement(Element& element)
    178178{
    179179    if (m_didSeePendingStylesheet && !element.renderer() && !m_document.isIgnoringPendingStylesheets()) {
     
    219219    }
    220220
    221     return update;
     221    auto beforeUpdate = resolvePseudoStyle(element, update, BEFORE);
     222    auto afterUpdate = resolvePseudoStyle(element, update, AFTER);
     223
     224    return { WTFMove(update), WTFMove(beforeUpdate), WTFMove(afterUpdate) };
     225}
     226
     227ElementUpdate TreeResolver::resolvePseudoStyle(Element& element, const ElementUpdate& elementUpdate, PseudoId pseudoId)
     228{
     229    if (!elementUpdate.style->hasPseudoStyle(pseudoId))
     230        return { };
     231    auto pseudoStyle = scope().styleResolver.pseudoStyleForElement(element, { pseudoId }, *elementUpdate.style);
     232
     233    PseudoElement* pseudoElement = pseudoId == BEFORE ? element.beforePseudoElement() : element.afterPseudoElement();
     234    if (!pseudoElement) {
     235        auto newPseudoElement = PseudoElement::create(element, pseudoId);
     236        pseudoElement = newPseudoElement.ptr();
     237        if (pseudoId == BEFORE)
     238            element.setBeforePseudoElement(WTFMove(newPseudoElement));
     239        else
     240            element.setAfterPseudoElement(WTFMove(newPseudoElement));
     241    }
     242
     243    return createAnimatedElementUpdate(WTFMove(pseudoStyle), *pseudoElement, elementUpdate.change);
    222244}
    223245
     
    238260ElementUpdate TreeResolver::createAnimatedElementUpdate(std::unique_ptr<RenderStyle> newStyle, Element& element, Change parentChange)
    239261{
    240     auto& animationController = element.document().frame()->animation();
     262    auto& animationController = m_document.frame()->animation();
    241263
    242264    auto* oldStyle = renderOrDisplayContentsStyle(element);
     
    409431                element.willRecalcStyle(parent.change);
    410432
    411             auto elementUpdate = resolveElement(element);
     433            auto elementUpdates = resolveElement(element);
    412434
    413435            if (element.hasCustomStyleResolveCallbacks())
    414                 element.didRecalcStyle(elementUpdate.change);
    415 
    416             style = elementUpdate.style.get();
    417             change = elementUpdate.change;
     436                element.didRecalcStyle(elementUpdates.update.change);
     437
     438            style = elementUpdates.update.style.get();
     439            change = elementUpdates.update.change;
    418440
    419441            if (affectedByPreviousSibling && change != Detach)
    420442                change = Force;
    421443
    422             if (elementUpdate.style)
    423                 m_update->addElement(element, parent.element, WTFMove(elementUpdate));
     444            if (elementUpdates.update.style)
     445                m_update->addElement(element, parent.element, WTFMove(elementUpdates));
    424446
    425447            clearNeedsStyleResolution(element);
  • trunk/Source/WebCore/style/StyleTreeResolver.h

    r218793 r223500  
    5252    std::unique_ptr<Update> resolve();
    5353
    54     static ElementUpdate createAnimatedElementUpdate(std::unique_ptr<RenderStyle>, Element&, Change parentChange);
    55 
    5654private:
    5755    std::unique_ptr<RenderStyle> styleForElement(Element&, const RenderStyle& inheritedStyle);
    5856
    5957    void resolveComposedTree();
    60     ElementUpdate resolveElement(Element&);
     58    ElementUpdates resolveElement(Element&);
     59    ElementUpdate createAnimatedElementUpdate(std::unique_ptr<RenderStyle>, Element&, Change parentChange);
     60    ElementUpdate resolvePseudoStyle(Element&, const ElementUpdate&, PseudoId);
    6161
    6262    struct Scope : RefCounted<Scope> {
  • trunk/Source/WebCore/style/StyleUpdate.cpp

    r220523 r223500  
    4242}
    4343
    44 const ElementUpdate* Update::elementUpdate(const Element& element) const
     44const ElementUpdates* Update::elementUpdates(const Element& element) const
    4545{
    4646    auto it = m_elements.find(&element);
     
    5050}
    5151
    52 ElementUpdate* Update::elementUpdate(const Element& element)
     52ElementUpdates* Update::elementUpdates(const Element& element)
    5353{
    5454    auto it = m_elements.find(&element);
     
    6868const RenderStyle* Update::elementStyle(const Element& element) const
    6969{
    70     if (auto* update = elementUpdate(element))
    71         return update->style.get();
     70    if (auto* updates = elementUpdates(element))
     71        return updates->update.style.get();
    7272    auto* renderer = element.renderer();
    7373    if (!renderer)
     
    7878RenderStyle* Update::elementStyle(const Element& element)
    7979{
    80     if (auto* update = elementUpdate(element))
    81         return update->style.get();
     80    if (auto* updates = elementUpdates(element))
     81        return updates->update.style.get();
    8282    auto* renderer = element.renderer();
    8383    if (!renderer)
     
    8686}
    8787
    88 void Update::addElement(Element& element, Element* parent, ElementUpdate&& elementUpdate)
     88void Update::addElement(Element& element, Element* parent, ElementUpdates&& elementUpdates)
    8989{
    9090    ASSERT(!m_elements.contains(&element));
     
    9292
    9393    addPossibleRoot(parent);
    94     m_elements.add(&element, WTFMove(elementUpdate));
     94    m_elements.add(&element, WTFMove(elementUpdates));
    9595}
    9696
  • trunk/Source/WebCore/style/StyleUpdate.h

    r221213 r223500  
    5858};
    5959
     60struct ElementUpdates {
     61#if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES)
     62    ElementUpdates() = default;
     63    ElementUpdates(ElementUpdate update, std::optional<ElementUpdate> beforePseudoElementUpdate, std::optional<ElementUpdate> afterPseudoElementUpdate)
     64        : update { WTFMove(update) }
     65        , beforePseudoElementUpdate { WTFMove(beforePseudoElementUpdate) }
     66        , afterPseudoElementUpdate { WTFMove(afterPseudoElementUpdate) }
     67    {
     68    }
     69#endif
     70    ElementUpdate update;
     71    std::optional<ElementUpdate> beforePseudoElementUpdate;
     72    std::optional<ElementUpdate> afterPseudoElementUpdate;
     73};
     74
    6075struct TextUpdate {
    6176#if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES)
     
    7994    const ListHashSet<ContainerNode*>& roots() const { return m_roots; }
    8095
    81     const ElementUpdate* elementUpdate(const Element&) const;
    82     ElementUpdate* elementUpdate(const Element&);
     96    const ElementUpdates* elementUpdates(const Element&) const;
     97    ElementUpdates* elementUpdates(const Element&);
    8398
    8499    const TextUpdate* textUpdate(const Text&) const;
     
    91106    unsigned size() const { return m_elements.size() + m_texts.size(); }
    92107
    93     void addElement(Element&, Element* parent, ElementUpdate&&);
     108    void addElement(Element&, Element* parent, ElementUpdates&&);
    94109    void addText(Text&, Element* parent, TextUpdate&&);
    95110    void addText(Text&, TextUpdate&&);
     
    100115    Document& m_document;
    101116    ListHashSet<ContainerNode*> m_roots;
    102     HashMap<const Element*, ElementUpdate> m_elements;
     117    HashMap<const Element*, ElementUpdates> m_elements;
    103118    HashMap<const Text*, TextUpdate> m_texts;
    104119};
Note: See TracChangeset for help on using the changeset viewer.