⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286112 in webkit


Ignore:
Timestamp:
Nov 22, 2021, 9:53:53 AM (5 years ago)
Author:
Antti Koivisto
Message:

Factor child change invalidation into class
https://bugs.webkit.org/show_bug.cgi?id=233311

Reviewed by Alan Bujtas.

Use similar pattern as ClassChangeInvalidation and others where we create a stack object scoped
over a DOM mutation. This will allow more sophisticated ruleset based invalidation in
future.

This patch moves the invalidation code from childrenChanged() to the new ChildChangeInvalidation class.
ChildChangeInvalidation is instantiated in ContainerNode and CharacterData mutation functions
that call childrenChanged(). It uses the same ChildChange argument type as childrenChanged().

There are no changes to invalidation functionality in this patch.

  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • dom/CharacterData.cpp:

(WebCore::makeChildChange):
(WebCore::CharacterData::parserAppendData):
(WebCore::CharacterData::setDataAndUpdate):
(WebCore::CharacterData::notifyParentAfterChange):

  • dom/CharacterData.h:
  • dom/ContainerNode.cpp:

(WebCore::ContainerNode::removeAllChildrenWithScriptAssertion):
(WebCore::makeChildChangeForRemoval):
(WebCore::ContainerNode::removeNodeWithScriptAssertion):
(WebCore::makeChildChangeForInsertion):
(WebCore::executeNodeInsertionWithScriptAssertion):
(WebCore::ContainerNode::insertBefore):
(WebCore::ContainerNode::parserInsertBefore):
(WebCore::ContainerNode::replaceChild):
(WebCore::ContainerNode::replaceAll):
(WebCore::ContainerNode::appendChildWithoutPreInsertionValidityCheck):
(WebCore::ContainerNode::parserAppendChild):
(WebCore::affectsElements):

  • dom/Element.cpp:

(WebCore::invalidateForSiblingCombinators):
(WebCore::Element::childTypeAllowed const):
(WebCore::Element::childrenChanged):
(WebCore::Element::finishParsingChildren):
(WebCore::checkForEmptyStyleChange): Deleted.
(WebCore::invalidateForForwardPositionalRules): Deleted.
(WebCore::invalidateForBackwardPositionalRules): Deleted.
(WebCore::checkForSiblingStyleChanges): Deleted.

  • dom/Element.h:
  • style/ChildChangeInvalidation.cpp: Added.

(WebCore::Style::ChildChangeInvalidation::ChildChangeInvalidation):
(WebCore::Style::ChildChangeInvalidation::~ChildChangeInvalidation):
(WebCore::Style::ChildChangeInvalidation::invalidateAfterChange):
(WebCore::Style::ChildChangeInvalidation::checkForEmptyStyleChange):
(WebCore::Style::invalidateForForwardPositionalRules):
(WebCore::Style::invalidateForBackwardPositionalRules):
(WebCore::Style::ChildChangeInvalidation::checkForSiblingStyleChanges):

  • style/ChildChangeInvalidation.h: Added.

(WebCore::Style::ChildChangeInvalidation::parentElement):

  • style/StyleAdjuster.h:
Location:
trunk/Source/WebCore
Files:
2 added
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r286107 r286112  
     12021-11-22  Antti Koivisto  <antti@apple.com>
     2
     3        Factor child change invalidation into class
     4        https://bugs.webkit.org/show_bug.cgi?id=233311
     5
     6        Reviewed by Alan Bujtas.
     7
     8        Use similar pattern as ClassChangeInvalidation and others where we create a stack object scoped
     9        over a DOM mutation. This will allow more sophisticated ruleset based invalidation in
     10        future.
     11
     12        This patch moves the invalidation code from childrenChanged() to the new ChildChangeInvalidation class.
     13        ChildChangeInvalidation is instantiated in ContainerNode and CharacterData mutation functions
     14        that call childrenChanged(). It uses the same ChildChange argument type as childrenChanged().
     15
     16        There are no changes to invalidation functionality in this patch.
     17
     18        * Sources.txt:
     19        * WebCore.xcodeproj/project.pbxproj:
     20        * dom/CharacterData.cpp:
     21        (WebCore::makeChildChange):
     22        (WebCore::CharacterData::parserAppendData):
     23        (WebCore::CharacterData::setDataAndUpdate):
     24        (WebCore::CharacterData::notifyParentAfterChange):
     25        * dom/CharacterData.h:
     26        * dom/ContainerNode.cpp:
     27        (WebCore::ContainerNode::removeAllChildrenWithScriptAssertion):
     28        (WebCore::makeChildChangeForRemoval):
     29        (WebCore::ContainerNode::removeNodeWithScriptAssertion):
     30        (WebCore::makeChildChangeForInsertion):
     31        (WebCore::executeNodeInsertionWithScriptAssertion):
     32        (WebCore::ContainerNode::insertBefore):
     33        (WebCore::ContainerNode::parserInsertBefore):
     34        (WebCore::ContainerNode::replaceChild):
     35        (WebCore::ContainerNode::replaceAll):
     36        (WebCore::ContainerNode::appendChildWithoutPreInsertionValidityCheck):
     37        (WebCore::ContainerNode::parserAppendChild):
     38        (WebCore::affectsElements):
     39        * dom/Element.cpp:
     40        (WebCore::invalidateForSiblingCombinators):
     41        (WebCore::Element::childTypeAllowed const):
     42        (WebCore::Element::childrenChanged):
     43        (WebCore::Element::finishParsingChildren):
     44        (WebCore::checkForEmptyStyleChange): Deleted.
     45        (WebCore::invalidateForForwardPositionalRules): Deleted.
     46        (WebCore::invalidateForBackwardPositionalRules): Deleted.
     47        (WebCore::checkForSiblingStyleChanges): Deleted.
     48        * dom/Element.h:
     49        * style/ChildChangeInvalidation.cpp: Added.
     50        (WebCore::Style::ChildChangeInvalidation::ChildChangeInvalidation):
     51        (WebCore::Style::ChildChangeInvalidation::~ChildChangeInvalidation):
     52        (WebCore::Style::ChildChangeInvalidation::invalidateAfterChange):
     53        (WebCore::Style::ChildChangeInvalidation::checkForEmptyStyleChange):
     54        (WebCore::Style::invalidateForForwardPositionalRules):
     55        (WebCore::Style::invalidateForBackwardPositionalRules):
     56        (WebCore::Style::ChildChangeInvalidation::checkForSiblingStyleChanges):
     57        * style/ChildChangeInvalidation.h: Added.
     58        (WebCore::Style::ChildChangeInvalidation::parentElement):
     59        * style/StyleAdjuster.h:
     60
    1612021-11-21  Alan Bujtas  <zalan@apple.com>
    262
  • trunk/Source/WebCore/Sources.txt

    r286091 r286112  
    25252525storage/StorageQuotaManager.cpp
    25262526style/AttributeChangeInvalidation.cpp
     2527style/ChildChangeInvalidation.cpp
    25272528style/ClassChangeInvalidation.cpp
    25282529style/ElementRuleCollector.cpp
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r286091 r286112  
    53435343                E4C279590CF9741900E97B98 /* RenderMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = E4C279570CF9741900E97B98 /* RenderMedia.h */; settings = {ATTRIBUTES = (Private, ); }; };
    53445344                E4C3B1FA0F0E4161009693F6 /* LegacyTileCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E4C3B1F90F0E4161009693F6 /* LegacyTileCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
     5345                E4C4C61A27452A7900A040E7 /* ChildChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4C4C61827452A7900A040E7 /* ChildChangeInvalidation.h */; };
    53455346                E4C91A0E1802343100A17F6D /* TextPaintStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = E4C91A0D1802343100A17F6D /* TextPaintStyle.h */; };
    53465347                E4C91A16180999F100A17F6D /* RenderTextLineBoxes.h in Headers */ = {isa = PBXBuildFile; fileRef = E4C91A15180999F100A17F6D /* RenderTextLineBoxes.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    1704717048                E4C3B1F90F0E4161009693F6 /* LegacyTileCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyTileCache.h; sourceTree = "<group>"; };
    1704817049                E4C3B1FB0F0E4170009693F6 /* LegacyTileCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LegacyTileCache.mm; sourceTree = "<group>"; };
     17050                E4C4C61827452A7900A040E7 /* ChildChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChildChangeInvalidation.h; sourceTree = "<group>"; };
     17051                E4C4C61B27452A8A00A040E7 /* ChildChangeInvalidation.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ChildChangeInvalidation.cpp; sourceTree = "<group>"; };
    1704917052                E4C91A0D1802343100A17F6D /* TextPaintStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextPaintStyle.h; sourceTree = "<group>"; };
    1705017053                E4C91A0F1802343900A17F6D /* TextPaintStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextPaintStyle.cpp; sourceTree = "<group>"; };
     
    3028330286                                E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */,
    3028430287                                E4ABABF42368C6EF00FA4345 /* CascadeLevel.h */,
     30288                                E4C4C61B27452A8A00A040E7 /* ChildChangeInvalidation.cpp */,
     30289                                E4C4C61827452A7900A040E7 /* ChildChangeInvalidation.h */,
    3028530290                                E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */,
    3028630291                                E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */,
     
    3273832743                                97B8FFD116AE7F960038388D /* CharacterReferenceParserInlines.h in Headers */,
    3273932744                                F55B3DB21251F12D003EF269 /* CheckboxInputType.h in Headers */,
     32745                                E4C4C61A27452A7900A040E7 /* ChildChangeInvalidation.h in Headers */,
    3274032746                                D619A308144E00BE004BC302 /* ChildListMutationScope.h in Headers */,
    3274132747                                A81872200977D3C0005826D9 /* ChildNodeList.h in Headers */,
  • trunk/Source/WebCore/dom/CharacterData.cpp

    r286091 r286112  
    2424
    2525#include "Attr.h"
     26#include "ChildChangeInvalidation.h"
    2627#include "ElementTraversal.h"
    2728#include "EventNames.h"
     
    7475}
    7576
     77static ContainerNode::ChildChange makeChildChange(CharacterData& characterData, ContainerNode::ChildChange::Source source)
     78{
     79    return {
     80        ContainerNode::ChildChange::Type::TextChanged,
     81        ElementTraversal::previousSibling(characterData),
     82        ElementTraversal::nextSibling(characterData),
     83        source
     84    };
     85}
     86
    7687unsigned CharacterData::parserAppendData(const String& string, unsigned offset, unsigned lengthLimit)
    7788{
     
    96107        return 0;
    97108
     109    auto childChange = makeChildChange(*this, ContainerNode::ChildChange::Source::Parser);
     110    std::optional<Style::ChildChangeInvalidation> styleInvalidation;
     111    if (auto* parent = parentNode())
     112        styleInvalidation.emplace(*parent, childChange);
     113
    98114    String oldData = m_data;
    99115    if (string.is8Bit())
     
    106122        downcast<Text>(*this).updateRendererAfterContentChange(oldLength, 0);
    107123
    108     notifyParentAfterChange(ContainerNode::ChildChange::Source::Parser);
     124    notifyParentAfterChange(childChange);
    109125
    110126    auto mutationRecipients = MutationObserverInterestGroup::createForCharacterDataMutation(*this);
     
    174190void CharacterData::setDataAndUpdate(const String& newData, unsigned offsetOfReplacedData, unsigned oldLength, unsigned newLength, UpdateLiveRanges shouldUpdateLiveRanges)
    175191{
     192    auto childChange = makeChildChange(*this, ContainerNode::ChildChange::Source::API);
     193
     194    std::optional<Style::ChildChangeInvalidation> styleInvalidation;
     195    if (auto* parent = parentNode())
     196        styleInvalidation.emplace(*parent, childChange);
     197
    176198    String oldData = m_data;
    177199    m_data = newData;
     
    192214        document().frame()->selection().textWasReplaced(this, offsetOfReplacedData, oldLength, newLength);
    193215
    194     notifyParentAfterChange(ContainerNode::ChildChange::Source::API);
     216    notifyParentAfterChange(childChange);
    195217
    196218    dispatchModifiedEvent(oldData);
    197219}
    198220
    199 void CharacterData::notifyParentAfterChange(ContainerNode::ChildChange::Source source)
     221void CharacterData::notifyParentAfterChange(const ContainerNode::ChildChange& childChange)
    200222{
    201223    document().incDOMTreeVersion();
     
    204226        return;
    205227
    206     ContainerNode::ChildChange change = {
    207         ContainerNode::ChildChange::Type::TextChanged,
    208         ElementTraversal::previousSibling(*this),
    209         ElementTraversal::nextSibling(*this),
    210         source
    211     };
    212 
    213     parentNode()->childrenChanged(change);
     228    parentNode()->childrenChanged(childChange);
    214229}
    215230
  • trunk/Source/WebCore/dom/CharacterData.h

    r286091 r286112  
    6666    String nodeValue() const final;
    6767    ExceptionOr<void> setNodeValue(const String&) final;
    68     void notifyParentAfterChange(ContainerNode::ChildChange::Source);
     68    void notifyParentAfterChange(const ContainerNode::ChildChange&);
    6969
    7070    String m_data;
  • trunk/Source/WebCore/dom/ContainerNode.cpp

    r286091 r286112  
    2626#include "AXObjectCache.h"
    2727#include "AllDescendantsCollection.h"
     28#include "ChildChangeInvalidation.h"
    2829#include "ChildListMutationScope.h"
    2930#include "ClassCollection.h"
     
    112113    disconnectSubframesIfNeeded(*this, DescendantsOnly);
    113114
     115    ContainerNode::ChildChange childChange { ChildChange::Type::AllChildrenRemoved, nullptr, nullptr, source };
     116
    114117    WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
    115118    ScriptDisallowedScope::InMainThread scriptDisallowedScope;
    116 
    117     if (UNLIKELY(isShadowRoot() || isInShadowTree()))
    118         containingShadowRoot()->willRemoveAllChildren(*this);
    119 
    120     document().nodeChildrenWillBeRemoved(*this);
    121 
    122     while (RefPtr<Node> child = m_firstChild) {
    123         removeBetween(nullptr, child->nextSibling(), *child);
    124         auto subtreeObservability = notifyChildNodeRemoved(*this, *child);
    125         if (source == ChildChange::Source::API && subtreeObservability == RemovedSubtreeObservability::MaybeObservableByRefPtr)
    126             willCreatePossiblyOrphanedTreeByRemoval(child.get());
     119    {
     120        Style::ChildChangeInvalidation styleInvalidation(*this, childChange);
     121
     122        if (UNLIKELY(isShadowRoot() || isInShadowTree()))
     123            containingShadowRoot()->willRemoveAllChildren(*this);
     124
     125        document().nodeChildrenWillBeRemoved(*this);
     126
     127        while (RefPtr<Node> child = m_firstChild) {
     128            removeBetween(nullptr, child->nextSibling(), *child);
     129            auto subtreeObservability = notifyChildNodeRemoved(*this, *child);
     130            if (source == ChildChange::Source::API && subtreeObservability == RemovedSubtreeObservability::MaybeObservableByRefPtr)
     131                willCreatePossiblyOrphanedTreeByRemoval(child.get());
     132        }
    127133    }
    128134
     
    130136
    131137    if (deferChildrenChanged == DeferChildrenChanged::No)
    132         childrenChanged(ContainerNode::ChildChange { ChildChange::Type::AllChildrenRemoved, nullptr, nullptr, source });
     138        childrenChanged(childChange);
    133139
    134140    return children;
     141}
     142
     143static ContainerNode::ChildChange makeChildChangeForRemoval(Node& childToRemove, ContainerNode::ChildChange::Source source)
     144{
     145    auto changeType = [&] {
     146        if (is<Element>(childToRemove))
     147            return ContainerNode::ChildChange::Type::ElementRemoved;
     148        if (is<Text>(childToRemove))
     149            return ContainerNode::ChildChange::Type::TextRemoved;
     150        return ContainerNode::ChildChange::Type::NonContentsChildRemoved;
     151    }();
     152
     153    return {
     154        changeType,
     155        ElementTraversal::previousSibling(childToRemove),
     156        ElementTraversal::nextSibling(childToRemove),
     157        source
     158    };
    135159}
    136160
     
    163187        return false;
    164188
    165     ChildChange change;
     189    auto childChange = makeChildChangeForRemoval(childToRemove, source);
     190
    166191    RemovedSubtreeObservability subtreeObservability;
    167192    {
    168193        WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
    169194        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
     195        Style::ChildChangeInvalidation styleInvalidation(*this, childChange);
    170196
    171197        if (UNLIKELY(isShadowRoot() || isInShadowTree()))
     
    179205        RefPtr<Node> previousSibling = childToRemove.previousSibling();
    180206        RefPtr<Node> nextSibling = childToRemove.nextSibling();
     207
    181208        removeBetween(previousSibling.get(), nextSibling.get(), childToRemove);
    182209        subtreeObservability = notifyChildNodeRemoved(*this, childToRemove);
    183 
    184         change.type = is<Element>(childToRemove) ?
    185             ChildChange::Type::ElementRemoved :
    186             (is<Text>(childToRemove) ?
    187                 ChildChange::Type::TextRemoved :
    188                 ChildChange::Type::NonContentsChildRemoved);
    189         change.previousSiblingElement = (!previousSibling || is<Element>(*previousSibling)) ? downcast<Element>(previousSibling.get()) : ElementTraversal::previousSibling(*previousSibling);
    190         change.nextSiblingElement = (!nextSibling || is<Element>(*nextSibling)) ? downcast<Element>(nextSibling.get()) : ElementTraversal::nextSibling(*nextSibling);
    191         change.source = source;
    192210    }
    193211
     
    198216
    199217    // FIXME: Move childrenChanged into ScriptDisallowedScope block.
    200     childrenChanged(change);
     218    childrenChanged(childChange);
    201219
    202220    return true;
     
    205223enum class ReplacedAllChildren { No, Yes };
    206224
     225static ContainerNode::ChildChange makeChildChangeForInsertion(ContainerNode& containerNode, Node& child, Node* beforeChild, ContainerNode::ChildChange::Source source, ReplacedAllChildren replacedAllChildren)
     226{
     227    if (replacedAllChildren == ReplacedAllChildren::Yes)
     228        return { ContainerNode::ChildChange::Type::AllChildrenReplaced, nullptr, nullptr, source };
     229
     230    auto changeType = [&] {
     231        if (is<Element>(child))
     232            return ContainerNode::ChildChange::Type::ElementInserted;
     233        if (is<Text>(child))
     234            return ContainerNode::ChildChange::Type::TextInserted;
     235        return ContainerNode::ChildChange::Type::NonContentsChildInserted;
     236    }();
     237
     238    return {
     239        changeType,
     240        beforeChild ? ElementTraversal::previousSibling(*beforeChild) : ElementTraversal::lastChild(containerNode),
     241        !beforeChild || is<Element>(*beforeChild) ? downcast<Element>(beforeChild) : ElementTraversal::nextSibling(*beforeChild),
     242        source
     243    };
     244}
     245
    207246template<typename DOMInsertionWork>
    208 static ALWAYS_INLINE void executeNodeInsertionWithScriptAssertion(ContainerNode& containerNode, Node& child,
     247static ALWAYS_INLINE void executeNodeInsertionWithScriptAssertion(ContainerNode& containerNode, Node& child, Node* beforeChild,
    209248    ContainerNode::ChildChange::Source source, ReplacedAllChildren replacedAllChildren, DOMInsertionWork doNodeInsertion)
    210249{
     250    auto childChange = makeChildChangeForInsertion(containerNode, child, beforeChild, source, replacedAllChildren);
     251
    211252    NodeVector postInsertionNotificationTargets;
    212253    {
    213254        WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates;
    214255        ScriptDisallowedScope::InMainThread scriptDisallowedScope;
     256        Style::ChildChangeInvalidation styleInvalidation(containerNode, childChange);
    215257
    216258        if (UNLIKELY(containerNode.isShadowRoot() || containerNode.isInShadowTree()))
     
    223265
    224266    // FIXME: Move childrenChanged into ScriptDisallowedScope block.
    225     if (replacedAllChildren == ReplacedAllChildren::Yes)
    226         containerNode.childrenChanged(ContainerNode::ChildChange { ContainerNode::ChildChange::Type::AllChildrenReplaced, nullptr, nullptr, source });
    227     else {
    228         containerNode.childrenChanged(ContainerNode::ChildChange {
    229             child.isElementNode() ?
    230                 ContainerNode::ChildChange::Type::ElementInserted :
    231                 (child.isTextNode() ?
    232                     ContainerNode::ChildChange::Type::TextInserted :
    233                     ContainerNode::ChildChange::Type::NonContentsChildInserted),
    234             ElementTraversal::previousSibling(child),
    235             ElementTraversal::nextSibling(child),
    236             source
    237         });
    238     }
     267    containerNode.childrenChanged(childChange);
    239268
    240269    ASSERT(ScriptDisallowedScope::InMainThread::isEventDispatchAllowedInSubtree(child));
     
    449478            break;
    450479
    451         executeNodeInsertionWithScriptAssertion(*this, child.get(), ChildChange::Source::API, ReplacedAllChildren::No, [&] {
     480        executeNodeInsertionWithScriptAssertion(*this, child.get(), next.ptr(), ChildChange::Source::API, ReplacedAllChildren::No, [&] {
    452481            child->setTreeScopeRecursively(treeScope());
    453482            insertBeforeCommon(next, child);
     
    508537        return;
    509538
    510     executeNodeInsertionWithScriptAssertion(*this, newChild, ChildChange::Source::Parser, ReplacedAllChildren::No, [&] {
     539    executeNodeInsertionWithScriptAssertion(*this, newChild, &nextChild, ChildChange::Source::Parser, ReplacedAllChildren::No, [&] {
    511540        if (&document() != &newChild.document())
    512541            document().adoptNode(newChild);
     
    582611            break;
    583612
    584         executeNodeInsertionWithScriptAssertion(*this, child.get(), ChildChange::Source::API, ReplacedAllChildren::No, [&] {
     613        executeNodeInsertionWithScriptAssertion(*this, child.get(), refChild.get(), ChildChange::Source::API, ReplacedAllChildren::No, [&] {
    585614            child->setTreeScopeRecursively(treeScope());
    586615            if (refChild)
     
    683712    removeAllChildrenWithScriptAssertion(ChildChange::Source::API, DeferChildrenChanged::Yes);
    684713
    685     executeNodeInsertionWithScriptAssertion(*this, *node, ChildChange::Source::API, ReplacedAllChildren::Yes, [&] {
     714    executeNodeInsertionWithScriptAssertion(*this, *node, nullptr, ChildChange::Source::API, ReplacedAllChildren::Yes, [&] {
    686715        InspectorInstrumentation::willInsertDOMNode(document(), *this);
    687716        node->setTreeScopeRecursively(treeScope());
     
    764793
    765794        // Append child to the end of the list
    766         executeNodeInsertionWithScriptAssertion(*this, child.get(), ChildChange::Source::API, ReplacedAllChildren::No, [&] {
     795        executeNodeInsertionWithScriptAssertion(*this, child.get(), nullptr, ChildChange::Source::API, ReplacedAllChildren::No, [&] {
    767796            child->setTreeScopeRecursively(treeScope());
    768797            appendChildCommon(child);
     
    780809    ASSERT(!hasTagName(HTMLNames::templateTag));
    781810
    782     executeNodeInsertionWithScriptAssertion(*this, newChild, ChildChange::Source::Parser, ReplacedAllChildren::No, [&] {
     811    executeNodeInsertionWithScriptAssertion(*this, newChild, nullptr, ChildChange::Source::Parser, ReplacedAllChildren::No, [&] {
    783812        if (&document() != &newChild.document())
    784813            document().adoptNode(newChild);
  • trunk/Source/WebCore/dom/Element.cpp

    r286091 r286112  
    3131#include "AttributeChangeInvalidation.h"
    3232#include "CSSParser.h"
     33#include "ChildChangeInvalidation.h"
    3334#include "Chrome.h"
    3435#include "ChromeClient.h"
     
    20392040}
    20402041
    2041 static void invalidateForSiblingCombinators(Element* sibling)
     2042void invalidateForSiblingCombinators(Element* sibling)
    20422043{
    20432044    for (; sibling; sibling = sibling->nextElementSibling()) {
     
    26432644    return false;
    26442645}
    2645 
    2646 static void checkForEmptyStyleChange(Element& element)
    2647 {
    2648     if (element.styleAffectedByEmpty()) {
    2649         auto* style = element.renderStyle();
    2650         if (!style || (!style->emptyState() || element.hasChildNodes()))
    2651             element.invalidateStyleForSubtree();
    2652     }
    2653 }
    2654 
    2655 
    2656 static void invalidateForForwardPositionalRules(Element& parent, Element* elementAfterChange)
    2657 {
    2658     bool childrenAffected = parent.childrenAffectedByForwardPositionalRules();
    2659     bool descendantsAffected = parent.descendantsAffectedByForwardPositionalRules();
    2660 
    2661     if (!childrenAffected && !descendantsAffected)
    2662         return;
    2663 
    2664     for (auto* sibling = elementAfterChange; sibling; sibling = sibling->nextElementSibling()) {
    2665         if (childrenAffected)
    2666             sibling->invalidateStyleInternal();
    2667         if (descendantsAffected) {
    2668             for (auto* siblingChild = sibling->firstElementChild(); siblingChild; siblingChild = siblingChild->nextElementSibling())
    2669                 siblingChild->invalidateStyleForSubtreeInternal();
    2670         }
    2671     }
    2672 }
    2673 
    2674 static void invalidateForBackwardPositionalRules(Element& parent, Element* elementBeforeChange)
    2675 {
    2676     bool childrenAffected = parent.childrenAffectedByBackwardPositionalRules();
    2677     bool descendantsAffected = parent.descendantsAffectedByBackwardPositionalRules();
    2678 
    2679     if (!childrenAffected && !descendantsAffected)
    2680         return;
    2681 
    2682     for (auto* sibling = elementBeforeChange; sibling; sibling = sibling->previousElementSibling()) {
    2683         if (childrenAffected)
    2684             sibling->invalidateStyleInternal();
    2685         if (descendantsAffected) {
    2686             for (auto* siblingChild = sibling->firstElementChild(); siblingChild; siblingChild = siblingChild->nextElementSibling())
    2687                 siblingChild->invalidateStyleForSubtreeInternal();
    2688         }
    2689     }
    2690 }
    2691 
    2692 enum SiblingCheckType { FinishedParsingChildren, SiblingElementRemoved, Other };
    2693 
    2694 static void checkForSiblingStyleChanges(Element& parent, SiblingCheckType checkType, Element* elementBeforeChange, Element* elementAfterChange)
    2695 {
    2696     // :empty selector.
    2697     checkForEmptyStyleChange(parent);
    2698 
    2699     if (parent.styleValidity() >= Style::Validity::SubtreeInvalid)
    2700         return;
    2701 
    2702     // :first-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
    2703     // In the DOM case, we only need to do something if |afterChange| is not 0.
    2704     // |afterChange| is 0 in the parser case, so it works out that we'll skip this block.
    2705     if (parent.childrenAffectedByFirstChildRules() && elementAfterChange) {
    2706         // Find our new first child.
    2707         RefPtr<Element> newFirstElement = ElementTraversal::firstChild(parent);
    2708         // Find the first element node following |afterChange|
    2709 
    2710         // This is the insert/append case.
    2711         if (newFirstElement != elementAfterChange) {
    2712             auto* style = elementAfterChange->renderStyle();
    2713             if (!style || style->firstChildState())
    2714                 elementAfterChange->invalidateStyleForSubtreeInternal();
    2715         }
    2716 
    2717         // We also have to handle node removal.
    2718         if (checkType == SiblingElementRemoved && newFirstElement == elementAfterChange && newFirstElement) {
    2719             auto* style = newFirstElement->renderStyle();
    2720             if (!style || !style->firstChildState())
    2721                 newFirstElement->invalidateStyleForSubtreeInternal();
    2722         }
    2723     }
    2724 
    2725     // :last-child.  In the parser callback case, we don't have to check anything, since we were right the first time.
    2726     // In the DOM case, we only need to do something if |afterChange| is not 0.
    2727     if (parent.childrenAffectedByLastChildRules() && elementBeforeChange) {
    2728         // Find our new last child.
    2729         RefPtr<Element> newLastElement = ElementTraversal::lastChild(parent);
    2730 
    2731         if (newLastElement != elementBeforeChange) {
    2732             auto* style = elementBeforeChange->renderStyle();
    2733             if (!style || style->lastChildState())
    2734                 elementBeforeChange->invalidateStyleForSubtreeInternal();
    2735         }
    2736 
    2737         // We also have to handle node removal.  The parser callback case is similar to node removal as well in that we need to change the last child
    2738         // to match now.
    2739         if ((checkType == SiblingElementRemoved || checkType == FinishedParsingChildren) && newLastElement == elementBeforeChange && newLastElement) {
    2740             auto* style = newLastElement->renderStyle();
    2741             if (!style || !style->lastChildState())
    2742                 newLastElement->invalidateStyleForSubtreeInternal();
    2743         }
    2744     }
    2745 
    2746     invalidateForSiblingCombinators(elementAfterChange);
    2747 
    2748     invalidateForForwardPositionalRules(parent, elementAfterChange);
    2749     invalidateForBackwardPositionalRules(parent, elementBeforeChange);
    2750 }
    2751 
    27522646void Element::childrenChanged(const ChildChange& change)
    27532647{
    27542648    ContainerNode::childrenChanged(change);
    2755     if (change.source == ChildChange::Source::Parser)
    2756         checkForEmptyStyleChange(*this);
    2757     else {
    2758         auto checkType = change.type == ChildChange::Type::ElementRemoved ? SiblingElementRemoved : Other;
    2759         checkForSiblingStyleChanges(*this, checkType, change.previousSiblingElement, change.nextSiblingElement);
    2760     }
    2761 
    2762     if (ShadowRoot* shadowRoot = this->shadowRoot()) {
     2649
     2650    if (auto* shadowRoot = this->shadowRoot()) {
    27632651        switch (change.type) {
    27642652        case ChildChange::Type::ElementInserted:
     
    28032691    ContainerNode::finishParsingChildren();
    28042692    setIsParsingChildrenFinished();
    2805     checkForSiblingStyleChanges(*this, FinishedParsingChildren, ElementTraversal::lastChild(*this), nullptr);
     2693
     2694    Style::ChildChangeInvalidation::invalidateAfterFinishedParsingChildren(*this);
    28062695}
    28072696
  • trunk/Source/WebCore/dom/Element.h

    r286091 r286112  
    764764};
    765765
     766void invalidateForSiblingCombinators(Element* sibling);
     767
    766768} // namespace WebCore
    767769
  • trunk/Source/WebCore/style/StyleAdjuster.h

    r286091 r286112  
    2727
    2828#include "RenderStyleConstants.h"
     29#include "TextSizeAdjustment.h"
    2930#include <wtf/OptionSet.h>
    3031
Note: See TracChangeset for help on using the changeset viewer.