Changeset 286112 in webkit
- Timestamp:
- Nov 22, 2021, 9:53:53 AM (5 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 2 added
- 9 edited
-
ChangeLog (modified) (1 diff)
-
Sources.txt (modified) (1 diff)
-
WebCore.xcodeproj/project.pbxproj (modified) (4 diffs)
-
dom/CharacterData.cpp (modified) (7 diffs)
-
dom/CharacterData.h (modified) (1 diff)
-
dom/ContainerNode.cpp (modified) (14 diffs)
-
dom/Element.cpp (modified) (4 diffs)
-
dom/Element.h (modified) (1 diff)
-
style/ChildChangeInvalidation.cpp (added)
-
style/ChildChangeInvalidation.h (added)
-
style/StyleAdjuster.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r286107 r286112 1 2021-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 1 61 2021-11-21 Alan Bujtas <zalan@apple.com> 2 62 -
trunk/Source/WebCore/Sources.txt
r286091 r286112 2525 2525 storage/StorageQuotaManager.cpp 2526 2526 style/AttributeChangeInvalidation.cpp 2527 style/ChildChangeInvalidation.cpp 2527 2528 style/ClassChangeInvalidation.cpp 2528 2529 style/ElementRuleCollector.cpp -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r286091 r286112 5343 5343 E4C279590CF9741900E97B98 /* RenderMedia.h in Headers */ = {isa = PBXBuildFile; fileRef = E4C279570CF9741900E97B98 /* RenderMedia.h */; settings = {ATTRIBUTES = (Private, ); }; }; 5344 5344 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 */; }; 5345 5346 E4C91A0E1802343100A17F6D /* TextPaintStyle.h in Headers */ = {isa = PBXBuildFile; fileRef = E4C91A0D1802343100A17F6D /* TextPaintStyle.h */; }; 5346 5347 E4C91A16180999F100A17F6D /* RenderTextLineBoxes.h in Headers */ = {isa = PBXBuildFile; fileRef = E4C91A15180999F100A17F6D /* RenderTextLineBoxes.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 17047 17048 E4C3B1F90F0E4161009693F6 /* LegacyTileCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LegacyTileCache.h; sourceTree = "<group>"; }; 17048 17049 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>"; }; 17049 17052 E4C91A0D1802343100A17F6D /* TextPaintStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextPaintStyle.h; sourceTree = "<group>"; }; 17050 17053 E4C91A0F1802343900A17F6D /* TextPaintStyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TextPaintStyle.cpp; sourceTree = "<group>"; }; … … 30283 30286 E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */, 30284 30287 E4ABABF42368C6EF00FA4345 /* CascadeLevel.h */, 30288 E4C4C61B27452A8A00A040E7 /* ChildChangeInvalidation.cpp */, 30289 E4C4C61827452A7900A040E7 /* ChildChangeInvalidation.h */, 30285 30290 E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */, 30286 30291 E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */, … … 32738 32743 97B8FFD116AE7F960038388D /* CharacterReferenceParserInlines.h in Headers */, 32739 32744 F55B3DB21251F12D003EF269 /* CheckboxInputType.h in Headers */, 32745 E4C4C61A27452A7900A040E7 /* ChildChangeInvalidation.h in Headers */, 32740 32746 D619A308144E00BE004BC302 /* ChildListMutationScope.h in Headers */, 32741 32747 A81872200977D3C0005826D9 /* ChildNodeList.h in Headers */, -
trunk/Source/WebCore/dom/CharacterData.cpp
r286091 r286112 24 24 25 25 #include "Attr.h" 26 #include "ChildChangeInvalidation.h" 26 27 #include "ElementTraversal.h" 27 28 #include "EventNames.h" … … 74 75 } 75 76 77 static 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 76 87 unsigned CharacterData::parserAppendData(const String& string, unsigned offset, unsigned lengthLimit) 77 88 { … … 96 107 return 0; 97 108 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 98 114 String oldData = m_data; 99 115 if (string.is8Bit()) … … 106 122 downcast<Text>(*this).updateRendererAfterContentChange(oldLength, 0); 107 123 108 notifyParentAfterChange( ContainerNode::ChildChange::Source::Parser);124 notifyParentAfterChange(childChange); 109 125 110 126 auto mutationRecipients = MutationObserverInterestGroup::createForCharacterDataMutation(*this); … … 174 190 void CharacterData::setDataAndUpdate(const String& newData, unsigned offsetOfReplacedData, unsigned oldLength, unsigned newLength, UpdateLiveRanges shouldUpdateLiveRanges) 175 191 { 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 176 198 String oldData = m_data; 177 199 m_data = newData; … … 192 214 document().frame()->selection().textWasReplaced(this, offsetOfReplacedData, oldLength, newLength); 193 215 194 notifyParentAfterChange( ContainerNode::ChildChange::Source::API);216 notifyParentAfterChange(childChange); 195 217 196 218 dispatchModifiedEvent(oldData); 197 219 } 198 220 199 void CharacterData::notifyParentAfterChange( ContainerNode::ChildChange::Source source)221 void CharacterData::notifyParentAfterChange(const ContainerNode::ChildChange& childChange) 200 222 { 201 223 document().incDOMTreeVersion(); … … 204 226 return; 205 227 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); 214 229 } 215 230 -
trunk/Source/WebCore/dom/CharacterData.h
r286091 r286112 66 66 String nodeValue() const final; 67 67 ExceptionOr<void> setNodeValue(const String&) final; 68 void notifyParentAfterChange( ContainerNode::ChildChange::Source);68 void notifyParentAfterChange(const ContainerNode::ChildChange&); 69 69 70 70 String m_data; -
trunk/Source/WebCore/dom/ContainerNode.cpp
r286091 r286112 26 26 #include "AXObjectCache.h" 27 27 #include "AllDescendantsCollection.h" 28 #include "ChildChangeInvalidation.h" 28 29 #include "ChildListMutationScope.h" 29 30 #include "ClassCollection.h" … … 112 113 disconnectSubframesIfNeeded(*this, DescendantsOnly); 113 114 115 ContainerNode::ChildChange childChange { ChildChange::Type::AllChildrenRemoved, nullptr, nullptr, source }; 116 114 117 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; 115 118 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 } 127 133 } 128 134 … … 130 136 131 137 if (deferChildrenChanged == DeferChildrenChanged::No) 132 childrenChanged( ContainerNode::ChildChange { ChildChange::Type::AllChildrenRemoved, nullptr, nullptr, source });138 childrenChanged(childChange); 133 139 134 140 return children; 141 } 142 143 static 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 }; 135 159 } 136 160 … … 163 187 return false; 164 188 165 ChildChange change; 189 auto childChange = makeChildChangeForRemoval(childToRemove, source); 190 166 191 RemovedSubtreeObservability subtreeObservability; 167 192 { 168 193 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; 169 194 ScriptDisallowedScope::InMainThread scriptDisallowedScope; 195 Style::ChildChangeInvalidation styleInvalidation(*this, childChange); 170 196 171 197 if (UNLIKELY(isShadowRoot() || isInShadowTree())) … … 179 205 RefPtr<Node> previousSibling = childToRemove.previousSibling(); 180 206 RefPtr<Node> nextSibling = childToRemove.nextSibling(); 207 181 208 removeBetween(previousSibling.get(), nextSibling.get(), childToRemove); 182 209 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;192 210 } 193 211 … … 198 216 199 217 // FIXME: Move childrenChanged into ScriptDisallowedScope block. 200 childrenChanged(ch ange);218 childrenChanged(childChange); 201 219 202 220 return true; … … 205 223 enum class ReplacedAllChildren { No, Yes }; 206 224 225 static 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 207 246 template<typename DOMInsertionWork> 208 static ALWAYS_INLINE void executeNodeInsertionWithScriptAssertion(ContainerNode& containerNode, Node& child, 247 static ALWAYS_INLINE void executeNodeInsertionWithScriptAssertion(ContainerNode& containerNode, Node& child, Node* beforeChild, 209 248 ContainerNode::ChildChange::Source source, ReplacedAllChildren replacedAllChildren, DOMInsertionWork doNodeInsertion) 210 249 { 250 auto childChange = makeChildChangeForInsertion(containerNode, child, beforeChild, source, replacedAllChildren); 251 211 252 NodeVector postInsertionNotificationTargets; 212 253 { 213 254 WidgetHierarchyUpdatesSuspensionScope suspendWidgetHierarchyUpdates; 214 255 ScriptDisallowedScope::InMainThread scriptDisallowedScope; 256 Style::ChildChangeInvalidation styleInvalidation(containerNode, childChange); 215 257 216 258 if (UNLIKELY(containerNode.isShadowRoot() || containerNode.isInShadowTree())) … … 223 265 224 266 // 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); 239 268 240 269 ASSERT(ScriptDisallowedScope::InMainThread::isEventDispatchAllowedInSubtree(child)); … … 449 478 break; 450 479 451 executeNodeInsertionWithScriptAssertion(*this, child.get(), ChildChange::Source::API, ReplacedAllChildren::No, [&] {480 executeNodeInsertionWithScriptAssertion(*this, child.get(), next.ptr(), ChildChange::Source::API, ReplacedAllChildren::No, [&] { 452 481 child->setTreeScopeRecursively(treeScope()); 453 482 insertBeforeCommon(next, child); … … 508 537 return; 509 538 510 executeNodeInsertionWithScriptAssertion(*this, newChild, ChildChange::Source::Parser, ReplacedAllChildren::No, [&] {539 executeNodeInsertionWithScriptAssertion(*this, newChild, &nextChild, ChildChange::Source::Parser, ReplacedAllChildren::No, [&] { 511 540 if (&document() != &newChild.document()) 512 541 document().adoptNode(newChild); … … 582 611 break; 583 612 584 executeNodeInsertionWithScriptAssertion(*this, child.get(), ChildChange::Source::API, ReplacedAllChildren::No, [&] {613 executeNodeInsertionWithScriptAssertion(*this, child.get(), refChild.get(), ChildChange::Source::API, ReplacedAllChildren::No, [&] { 585 614 child->setTreeScopeRecursively(treeScope()); 586 615 if (refChild) … … 683 712 removeAllChildrenWithScriptAssertion(ChildChange::Source::API, DeferChildrenChanged::Yes); 684 713 685 executeNodeInsertionWithScriptAssertion(*this, *node, ChildChange::Source::API, ReplacedAllChildren::Yes, [&] {714 executeNodeInsertionWithScriptAssertion(*this, *node, nullptr, ChildChange::Source::API, ReplacedAllChildren::Yes, [&] { 686 715 InspectorInstrumentation::willInsertDOMNode(document(), *this); 687 716 node->setTreeScopeRecursively(treeScope()); … … 764 793 765 794 // 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, [&] { 767 796 child->setTreeScopeRecursively(treeScope()); 768 797 appendChildCommon(child); … … 780 809 ASSERT(!hasTagName(HTMLNames::templateTag)); 781 810 782 executeNodeInsertionWithScriptAssertion(*this, newChild, ChildChange::Source::Parser, ReplacedAllChildren::No, [&] {811 executeNodeInsertionWithScriptAssertion(*this, newChild, nullptr, ChildChange::Source::Parser, ReplacedAllChildren::No, [&] { 783 812 if (&document() != &newChild.document()) 784 813 document().adoptNode(newChild); -
trunk/Source/WebCore/dom/Element.cpp
r286091 r286112 31 31 #include "AttributeChangeInvalidation.h" 32 32 #include "CSSParser.h" 33 #include "ChildChangeInvalidation.h" 33 34 #include "Chrome.h" 34 35 #include "ChromeClient.h" … … 2039 2040 } 2040 2041 2041 staticvoid invalidateForSiblingCombinators(Element* sibling)2042 void invalidateForSiblingCombinators(Element* sibling) 2042 2043 { 2043 2044 for (; sibling; sibling = sibling->nextElementSibling()) { … … 2643 2644 return false; 2644 2645 } 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 child2738 // 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 2752 2646 void Element::childrenChanged(const ChildChange& change) 2753 2647 { 2754 2648 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()) { 2763 2651 switch (change.type) { 2764 2652 case ChildChange::Type::ElementInserted: … … 2803 2691 ContainerNode::finishParsingChildren(); 2804 2692 setIsParsingChildrenFinished(); 2805 checkForSiblingStyleChanges(*this, FinishedParsingChildren, ElementTraversal::lastChild(*this), nullptr); 2693 2694 Style::ChildChangeInvalidation::invalidateAfterFinishedParsingChildren(*this); 2806 2695 } 2807 2696 -
trunk/Source/WebCore/dom/Element.h
r286091 r286112 764 764 }; 765 765 766 void invalidateForSiblingCombinators(Element* sibling); 767 766 768 } // namespace WebCore 767 769 -
trunk/Source/WebCore/style/StyleAdjuster.h
r286091 r286112 27 27 28 28 #include "RenderStyleConstants.h" 29 #include "TextSizeAdjustment.h" 29 30 #include <wtf/OptionSet.h> 30 31
Note:
See TracChangeset
for help on using the changeset viewer.