Changeset 196629 in webkit
- Timestamp:
- Feb 16, 2016 12:20:58 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r196628 r196629 1 2016-02-15 Antti Koivisto <antti@apple.com> 2 3 Optimize style invalidations for attribute selectors 4 https://bugs.webkit.org/show_bug.cgi?id=154242 5 6 Reviewed by Andreas Kling. 7 8 * fast/css/style-invalidation-attribute-change-descendants-expected.txt: Added. 9 * fast/css/style-invalidation-attribute-change-descendants.html: Added. 10 1 11 2016-02-16 Chris Dumez <cdumez@apple.com> 2 12 -
trunk/Source/WebCore/CMakeLists.txt
r196622 r196629 2631 2631 storage/StorageNamespaceProvider.cpp 2632 2632 2633 style/AttributeChangeInvalidation.cpp 2633 2634 style/ClassChangeInvalidation.cpp 2634 2635 style/InlineTextBoxStyle.cpp -
trunk/Source/WebCore/ChangeLog
r196628 r196629 1 2016-02-15 Antti Koivisto <antti@apple.com> 2 3 Optimize style invalidations for attribute selectors 4 https://bugs.webkit.org/show_bug.cgi?id=154242 5 6 Reviewed by Andreas Kling. 7 8 Currently we invalidate the whole element subtree if there are any attribute selectors for the changed attribute. 9 This is slow as generally few if any elements are really affected. Using attribute selectors for dynamic styling 10 should be performant. 11 12 This patch implements optimization strategy for attributes similar to what we already have for classes: 13 14 - Collect a map of all rules that contains descendant-affecting attribute selectors for a given attribute. 15 - When an attribute value changes check if there are any such rules for it. 16 - Check if the value change affects the results of any of the attribute selectors. 17 - Only if it does invalidate the exact descendant elements affected by the rules. 18 19 Test: fast/css/style-invalidation-attribute-change-descendants.html 20 21 * WebCore.xcodeproj/project.pbxproj: 22 * css/DocumentRuleSets.cpp: 23 (WebCore::DocumentRuleSets::ancestorClassRules): 24 (WebCore::DocumentRuleSets::ancestorAttributeRulesForHTML): 25 26 Create optimization RuleSets when needed. 27 28 * css/DocumentRuleSets.h: 29 (WebCore::DocumentRuleSets::uncommonAttribute): 30 (WebCore::DocumentRuleSets::features): 31 * css/RuleFeature.cpp: 32 (WebCore::RuleFeatureSet::recursivelyCollectFeaturesFromSelector): 33 (WebCore::makeAttributeSelectorKey): 34 (WebCore::RuleFeatureSet::collectFeatures): 35 36 Collect rules with descendant affecting attribute selectors. 37 38 (WebCore::RuleFeatureSet::add): 39 (WebCore::RuleFeatureSet::clear): 40 (WebCore::RuleFeatureSet::shrinkToFit): 41 * css/RuleFeature.h: 42 * css/SelectorChecker.cpp: 43 (WebCore::anyAttributeMatches): 44 (WebCore::SelectorChecker::attributeSelectorMatches): 45 46 Expose function for matching single attribute selectors. 47 48 (WebCore::canMatchHoverOrActiveInQuirksMode): 49 * css/SelectorChecker.h: 50 * dom/Attr.cpp: 51 (WebCore::Attr::setValue): 52 (WebCore::Attr::childrenChanged): 53 * dom/Element.cpp: 54 (WebCore::Element::setAttributeInternal): 55 (WebCore::makeIdForStyleResolution): 56 (WebCore::Element::attributeChanged): 57 (WebCore::Element::removeAttributeInternal): 58 (WebCore::Element::addAttributeInternal): 59 (WebCore::Element::removeAttribute): 60 61 Add AttributeChangeInvalidation where needed. 62 63 (WebCore::Element::needsStyleInvalidation): 64 65 Move to Element from ClassChangeInvalidation. 66 67 (WebCore::Element::willModifyAttribute): 68 69 No more full style invalidation on attribute change. 70 71 * style/AttributeChangeInvalidation.cpp: Added. 72 (WebCore::Style::AttributeChangeInvalidation::invalidateStyle): 73 74 Invalidate local style. 75 Check if we need to invalidate descendants by looking into ancestorAttributeRules. 76 77 (WebCore::Style::AttributeChangeInvalidation::invalidateDescendants): 78 79 Use StyleInvalidationAnalysis to invalidate the subtree for the relevant rules. 80 81 * style/AttributeChangeInvalidation.h: Added. 82 (WebCore::Style::AttributeChangeInvalidation::needsInvalidation): 83 (WebCore::Style::AttributeChangeInvalidation::AttributeChangeInvalidation): 84 (WebCore::Style::AttributeChangeInvalidation::~AttributeChangeInvalidation): 85 86 If needed, invalidate descendants before and after attribute change to catch rules that start and stop applying. 87 1 88 2016-02-16 Chris Dumez <cdumez@apple.com> 2 89 -
trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj
r196604 r196629 19296 19296 <ClCompile Include="..\storage\StorageMap.cpp" /> 19297 19297 <ClCompile Include="..\storage\StorageNamespaceProvider.cpp" /> 19298 <ClCompile Include="..\style\AttributeChangeInvalidation.cpp" /> 19298 19299 <ClCompile Include="..\style\ClassChangeInvalidation.cpp" /> 19299 19300 <ClCompile Include="..\style\InlineTextBoxStyle.cpp" /> … … 22866 22867 <ClInclude Include="..\storage\StorageNamespace.h" /> 22867 22868 <ClInclude Include="..\storage\StorageNamespaceProvider.h" /> 22869 <ClInclude Include="..\style\AttributeChangeInvalidation.h" /> 22868 22870 <ClInclude Include="..\style\ClassChangeInvalidation.h" /> 22869 22871 <ClInclude Include="..\style\InlineTextBoxStyle.h" /> -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r196622 r196629 6638 6638 E4A814D41C6DEC4000BF85AC /* ClassChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */; }; 6639 6639 E4A814D61C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */; }; 6640 E4A814D81C70E10500BF85AC /* AttributeChangeInvalidation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A814D71C70E10500BF85AC /* AttributeChangeInvalidation.cpp */; }; 6641 E4A814DA1C70E10D00BF85AC /* AttributeChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */; }; 6640 6642 E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1517D1BB950009FB31 /* ElementIterator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 6641 6643 E4AE7C1A17D232350009FB31 /* ElementAncestorIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 14644 14646 E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassChangeInvalidation.h; sourceTree = "<group>"; }; 14645 14647 E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassChangeInvalidation.cpp; sourceTree = "<group>"; }; 14648 E4A814D71C70E10500BF85AC /* AttributeChangeInvalidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AttributeChangeInvalidation.cpp; sourceTree = "<group>"; }; 14649 E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AttributeChangeInvalidation.h; sourceTree = "<group>"; }; 14646 14650 E4AE7C1517D1BB950009FB31 /* ElementIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIterator.h; sourceTree = "<group>"; }; 14647 14651 E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementAncestorIterator.h; sourceTree = "<group>"; }; … … 23434 23438 isa = PBXGroup; 23435 23439 children = ( 23440 E4A814D71C70E10500BF85AC /* AttributeChangeInvalidation.cpp */, 23441 E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */, 23436 23442 E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */, 23437 23443 E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */, … … 25910 25916 49ECEB6E1499790D00CDD3A4 /* FilterOperation.h in Headers */, 25911 25917 49ECEB701499790D00CDD3A4 /* FilterOperations.h in Headers */, 25918 E4A814DA1C70E10D00BF85AC /* AttributeChangeInvalidation.h in Headers */, 25912 25919 372C00D9129619F8005C9575 /* FindOptions.h in Headers */, 25913 25920 A8CFF04F0A154F09000A4234 /* FixedTableLayout.h in Headers */, … … 30441 30448 9BD4E9161C462872005065BC /* JSCustomElementInterface.cpp in Sources */, 30442 30449 514C76380CE9225E007EF3CD /* JSSQLTransaction.cpp in Sources */, 30450 E4A814D81C70E10500BF85AC /* AttributeChangeInvalidation.cpp in Sources */, 30443 30451 B59DD69E11902A42007E9684 /* JSSQLTransactionCallback.cpp in Sources */, 30444 30452 1AD2316E0CD269E700C1F194 /* JSSQLTransactionCustom.cpp in Sources */, -
trunk/Source/WebCore/css/DocumentRuleSets.cpp
r196555 r196629 119 119 RuleSet* DocumentRuleSets::ancestorClassRules(AtomicStringImpl* className) const 120 120 { 121 auto addResult = m_ancestorClassRuleSet .add(className, nullptr);121 auto addResult = m_ancestorClassRuleSets.add(className, nullptr); 122 122 if (addResult.isNewEntry) { 123 123 if (auto* rules = m_features.ancestorClassRules.get(className)) … … 127 127 } 128 128 129 const DocumentRuleSets::AttributeRules* DocumentRuleSets::ancestorAttributeRulesForHTML(AtomicStringImpl* attributeName) const 130 { 131 auto addResult = m_ancestorAttributeRuleSetsForHTML.add(attributeName, nullptr); 132 auto& value = addResult.iterator->value; 133 if (addResult.isNewEntry) { 134 if (auto* rules = m_features.ancestorAttributeRulesForHTML.get(attributeName)) { 135 value = std::make_unique<AttributeRules>(); 136 value->attributeSelectors.reserveCapacity(rules->selectors.size()); 137 for (auto* selector : rules->selectors.values()) 138 value->attributeSelectors.uncheckedAppend(selector); 139 value->ruleSet = makeRuleSet(rules->features); 140 } 141 } 142 return value.get(); 143 } 144 129 145 } // namespace WebCore -
trunk/Source/WebCore/css/DocumentRuleSets.h
r196555 r196629 53 53 RuleSet* ancestorClassRules(AtomicStringImpl* className) const; 54 54 55 struct AttributeRules { 56 Vector<const CSSSelector*> attributeSelectors; 57 std::unique_ptr<RuleSet> ruleSet; 58 }; 59 const AttributeRules* ancestorAttributeRulesForHTML(AtomicStringImpl*) const; 60 55 61 void initUserStyle(ExtensionStyleSheets&, const MediaQueryEvaluator&, StyleResolver&); 56 62 void resetAuthorStyle(); … … 68 74 mutable std::unique_ptr<RuleSet> m_siblingRuleSet; 69 75 mutable std::unique_ptr<RuleSet> m_uncommonAttributeRuleSet; 70 mutable HashMap<AtomicStringImpl*, std::unique_ptr<RuleSet>> m_ancestorClassRuleSet; 76 mutable HashMap<AtomicStringImpl*, std::unique_ptr<RuleSet>> m_ancestorClassRuleSets; 77 mutable HashMap<AtomicStringImpl*, std::unique_ptr<AttributeRules>> m_ancestorAttributeRuleSetsForHTML; 71 78 }; 72 79 -
trunk/Source/WebCore/css/RuleFeature.cpp
r196383 r196629 47 47 selectorFeatures.classesMatchingAncestors.append(selector->value().impl()); 48 48 } else if (selector->isAttributeSelector()) { 49 attributeCanonicalLocalNamesInRules.add(selector->attributeCanonicalLocalName().impl()); 50 attributeLocalNamesInRules.add(selector->attribute().localName().impl()); 49 auto* canonicalLocalName = selector->attributeCanonicalLocalName().impl(); 50 auto* localName = selector->attribute().localName().impl(); 51 attributeCanonicalLocalNamesInRules.add(canonicalLocalName); 52 attributeLocalNamesInRules.add(localName); 53 if (matchesAncestor) 54 selectorFeatures.attributeSelectorsMatchingAncestors.append(selector); 51 55 } else if (selector->match() == CSSSelector::PseudoElement) { 52 56 switch (selector->pseudoElementType()) { … … 79 83 } 80 84 85 static std::pair<AtomicStringImpl*, unsigned> makeAttributeSelectorKey(const CSSSelector& selector) 86 { 87 bool caseInsensitive = selector.attributeValueMatchingIsCaseInsensitive(); 88 unsigned matchAndCase = static_cast<unsigned>(selector.match()) << 1 | caseInsensitive; 89 return std::make_pair(selector.attributeCanonicalLocalName().impl(), matchAndCase); 90 } 91 81 92 void RuleFeatureSet::collectFeatures(const RuleData& ruleData) 82 93 { … … 92 103 addResult.iterator->value = std::make_unique<Vector<RuleFeature>>(); 93 104 addResult.iterator->value->append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); 105 } 106 for (auto* selector : selectorFeatures.attributeSelectorsMatchingAncestors) { 107 // Hashing by attributeCanonicalLocalName makes this HTML specific. 108 auto addResult = ancestorAttributeRulesForHTML.add(selector->attributeCanonicalLocalName().impl(), nullptr); 109 if (addResult.isNewEntry) 110 addResult.iterator->value = std::make_unique<AttributeRules>(); 111 auto& rules = *addResult.iterator->value; 112 rules.features.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), ruleData.hasDocumentSecurityOrigin())); 113 // Deduplicate selectors. 114 rules.selectors.add(makeAttributeSelectorKey(*selector), selector); 94 115 } 95 116 } … … 110 131 addResult.iterator->value->appendVector(*keyValuePair.value); 111 132 } 133 for (auto& keyValuePair : other.ancestorAttributeRulesForHTML) { 134 auto addResult = ancestorAttributeRulesForHTML.add(keyValuePair.key, nullptr); 135 if (addResult.isNewEntry) 136 addResult.iterator->value = std::make_unique<AttributeRules>(); 137 auto& rules = *addResult.iterator->value; 138 rules.features.appendVector(keyValuePair.value->features); 139 for (auto& selectorPair : keyValuePair.value->selectors) 140 rules.selectors.add(selectorPair.key, selectorPair.value); 141 } 112 142 usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules; 113 143 usesFirstLetterRules = usesFirstLetterRules || other.usesFirstLetterRules; … … 123 153 uncommonAttributeRules.clear(); 124 154 ancestorClassRules.clear(); 155 ancestorAttributeRulesForHTML.clear(); 125 156 usesFirstLineRules = false; 126 157 usesFirstLetterRules = false; … … 133 164 for (auto& rules : ancestorClassRules.values()) 134 165 rules->shrinkToFit(); 166 for (auto& rules : ancestorAttributeRulesForHTML.values()) 167 rules->features.shrinkToFit(); 135 168 } 136 169 -
trunk/Source/WebCore/css/RuleFeature.h
r196383 r196629 23 23 #define RuleFeature_h 24 24 25 #include "CSSSelector.h" 25 26 #include <wtf/Forward.h> 26 27 #include <wtf/HashMap.h> … … 30 31 namespace WebCore { 31 32 32 class CSSSelector;33 33 class RuleData; 34 34 class StyleRule; … … 59 59 Vector<RuleFeature> uncommonAttributeRules; 60 60 HashMap<AtomicStringImpl*, std::unique_ptr<Vector<RuleFeature>>> ancestorClassRules; 61 62 struct AttributeRules { 63 HashMap<std::pair<AtomicStringImpl*, unsigned>, const CSSSelector*> selectors; 64 Vector<RuleFeature> features; 65 }; 66 HashMap<AtomicStringImpl*, std::unique_ptr<AttributeRules>> ancestorAttributeRulesForHTML; 61 67 bool usesFirstLineRules { false }; 62 68 bool usesFirstLetterRules { false }; … … 66 72 bool hasSiblingSelector { false }; 67 73 Vector<AtomicStringImpl*> classesMatchingAncestors; 74 Vector<const CSSSelector*> attributeSelectorsMatchingAncestors; 68 75 }; 69 76 void recursivelyCollectFeaturesFromSelector(SelectorFeatures&, const CSSSelector&, bool matchesAncestor = false); -
trunk/Source/WebCore/css/SelectorChecker.cpp
r195311 r196629 517 517 518 518 return false; 519 } 520 521 bool SelectorChecker::attributeSelectorMatches(const Element& element, const QualifiedName& attributeName, const AtomicString& attributeValue, const CSSSelector& selector) 522 { 523 ASSERT(selector.isAttributeSelector()); 524 auto& selectorAttribute = selector.attribute(); 525 auto& selectorName = element.isHTMLElement() ? selector.attributeCanonicalLocalName() : selectorAttribute.localName(); 526 if (!Attribute::nameMatchesFilter(attributeName, selectorAttribute.prefix(), selectorName, selectorAttribute.namespaceURI())) 527 return false; 528 bool caseSensitive = true; 529 if (selector.attributeValueMatchingIsCaseInsensitive()) 530 caseSensitive = false; 531 else if (element.document().isHTMLDocument() && element.isHTMLElement() && !HTMLDocument::isCaseSensitiveAttribute(selector.attribute())) 532 caseSensitive = false; 533 return attributeValueMatches(Attribute(attributeName, attributeValue), selector.match(), selector.value(), caseSensitive); 519 534 } 520 535 -
trunk/Source/WebCore/css/SelectorChecker.h
r195311 r196629 120 120 static bool isCommonPseudoClassSelector(const CSSSelector*); 121 121 static bool matchesFocusPseudoClass(const Element&); 122 static bool attributeSelectorMatches(const Element&, const QualifiedName&, const AtomicString& attributeValue, const CSSSelector&); 122 123 123 124 enum LinkMatchMask { MatchDefault = 0, MatchLink = 1, MatchVisited = 2, MatchAll = MatchLink | MatchVisited }; -
trunk/Source/WebCore/dom/Attr.cpp
r194496 r196629 24 24 #include "Attr.h" 25 25 26 #include "AttributeChangeInvalidation.h" 26 27 #include "Event.h" 27 28 #include "ExceptionCode.h" … … 109 110 m_ignoreChildrenChanged++; 110 111 removeChildren(); 111 if (m_element) 112 if (m_element) { 113 Style::AttributeChangeInvalidation styleInvalidation(*m_element, qualifiedName(), elementAttribute().value(), value); 112 114 elementAttribute().setValue(value); 113 else115 } else 114 116 m_standaloneValue = value; 115 117 createTextChild(); … … 164 166 m_element->willModifyAttribute(qualifiedName(), oldValue, newValue); 165 167 166 if (m_element) 168 if (m_element) { 169 Style::AttributeChangeInvalidation styleInvalidation(*m_element, qualifiedName(), oldValue, newValue); 167 170 elementAttribute().setValue(newValue); 168 else171 } else 169 172 m_standaloneValue = newValue; 170 173 -
trunk/Source/WebCore/dom/Element.cpp
r196598 r196629 29 29 #include "AXObjectCache.h" 30 30 #include "Attr.h" 31 #include "AttributeChangeInvalidation.h" 31 32 #include "CSSParser.h" 32 33 #include "Chrome.h" … … 1183 1184 } 1184 1185 1186 if (inSynchronizationOfLazyAttribute) { 1187 ensureUniqueElementData().attributeAt(index).setValue(newValue); 1188 return; 1189 } 1190 1185 1191 const Attribute& attribute = attributeAt(index); 1192 QualifiedName attributeName = attribute.name(); 1186 1193 AtomicString oldValue = attribute.value(); 1187 bool valueChanged = newValue != oldValue; 1188 QualifiedName attributeName = (!inSynchronizationOfLazyAttribute || valueChanged) ? attribute.name() : name; 1189 1190 if (!inSynchronizationOfLazyAttribute) 1191 willModifyAttribute(attributeName, oldValue, newValue); 1192 1193 if (valueChanged) { 1194 1195 willModifyAttribute(attributeName, oldValue, newValue); 1196 1197 if (newValue != oldValue) { 1194 1198 // If there is an Attr node hooked to this attribute, the Attr::setValue() call below 1195 1199 // will write into the ElementData. 1196 1200 // FIXME: Refactor this so it makes some sense. 1197 if (RefPtr<Attr> attrNode = inSynchronizationOfLazyAttribute ? nullptr :attrIfExists(attributeName))1201 if (RefPtr<Attr> attrNode = attrIfExists(attributeName)) 1198 1202 attrNode->setValue(newValue); 1199 else 1203 else { 1204 Style::AttributeChangeInvalidation styleInvalidation(*this, name, oldValue, newValue); 1200 1205 ensureUniqueElementData().attributeAt(index).setValue(newValue); 1201 }1202 1203 if (!inSynchronizationOfLazyAttribute) 1204 1206 } 1207 } 1208 1209 didModifyAttribute(attributeName, oldValue, newValue); 1205 1210 } 1206 1211 … … 1269 1274 invalidateNodeListAndCollectionCachesInAncestors(&name, this); 1270 1275 1271 // If there is currently no StyleResolver, we can't be sure that this attribute change won't affect style.1272 shouldInvalidateStyle |= !styleResolver;1273 1274 1276 if (shouldInvalidateStyle) 1275 1277 setNeedsStyleRecalc(); … … 2051 2053 AtomicString valueBeingRemoved = elementData.attributeAt(index).value(); 2052 2054 2053 if (!inSynchronizationOfLazyAttribute) {2054 if (!valueBeingRemoved.isNull())2055 willModifyAttribute(name, valueBeingRemoved, nullAtom);2056 }2057 2058 2055 if (RefPtr<Attr> attrNode = attrIfExists(name)) 2059 2056 detachAttrNodeFromElementWithValue(attrNode.get(), elementData.attributeAt(index).value()); 2060 2057 2061 elementData.removeAttribute(index); 2062 2063 if (!inSynchronizationOfLazyAttribute) 2064 didRemoveAttribute(name, valueBeingRemoved); 2058 if (inSynchronizationOfLazyAttribute) { 2059 elementData.removeAttribute(index); 2060 return; 2061 } 2062 2063 if (!valueBeingRemoved.isNull()) 2064 willModifyAttribute(name, valueBeingRemoved, nullAtom); 2065 2066 { 2067 Style::AttributeChangeInvalidation styleInvalidation(*this, name, valueBeingRemoved, nullAtom); 2068 elementData.removeAttribute(index); 2069 } 2070 2071 didRemoveAttribute(name, valueBeingRemoved); 2065 2072 } 2066 2073 2067 2074 void Element::addAttributeInternal(const QualifiedName& name, const AtomicString& value, SynchronizationOfLazyAttribute inSynchronizationOfLazyAttribute) 2068 2075 { 2069 if (!inSynchronizationOfLazyAttribute) 2070 willModifyAttribute(name, nullAtom, value); 2071 ensureUniqueElementData().addAttribute(name, value); 2072 if (!inSynchronizationOfLazyAttribute) 2073 didAddAttribute(name, value); 2076 if (inSynchronizationOfLazyAttribute) { 2077 ensureUniqueElementData().addAttribute(name, value); 2078 return; 2079 } 2080 2081 willModifyAttribute(name, nullAtom, value); 2082 { 2083 Style::AttributeChangeInvalidation styleInvalidation(*this, name, nullAtom, value); 2084 ensureUniqueElementData().addAttribute(name, value); 2085 } 2086 didAddAttribute(name, value); 2074 2087 } 2075 2088 … … 2486 2499 } 2487 2500 2501 bool Element::needsStyleInvalidation() const 2502 { 2503 if (!inRenderedDocument()) 2504 return false; 2505 if (styleChangeType() >= FullStyleChange) 2506 return false; 2507 if (!document().styleResolverIfExists()) 2508 return false; 2509 2510 return true; 2511 } 2512 2488 2513 void Element::setStyleAffectedByEmpty() 2489 2514 { … … 3081 3106 } 3082 3107 3083 if (oldValue != newValue) {3084 auto styleResolver = document().styleResolverIfExists();3085 if (styleResolver && styleResolver->hasSelectorForAttribute(*this, name.localName()))3086 setNeedsStyleRecalc();3087 }3088 3089 3108 if (std::unique_ptr<MutationObserverInterestGroup> recipients = MutationObserverInterestGroup::createForAttributesMutation(*this, name)) 3090 3109 recipients->enqueueMutationRecord(MutationRecord::createAttributes(*this, name, oldValue)); -
trunk/Source/WebCore/dom/Element.h
r196598 r196629 280 280 virtual RenderStyle* computedStyle(PseudoId = NOPSEUDO) override; 281 281 282 bool needsStyleInvalidation() const; 283 282 284 // Methods for indicating the style is affected by dynamic updates (e.g., children changing, our position changing in our sibling list, etc.) 283 285 bool styleAffectedByEmpty() const { return hasRareData() && rareDataStyleAffectedByEmpty(); } -
trunk/Source/WebCore/style/ClassChangeInvalidation.h
r196560 r196629 47 47 using ClassChangeVector = Vector<AtomicStringImpl*, 4>; 48 48 49 static bool needsInvalidation(const Element&);50 49 void computeClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses); 51 50 void invalidateStyle(const ClassChangeVector&); … … 60 59 }; 61 60 62 inline bool ClassChangeInvalidation::needsInvalidation(const Element& element)63 {64 if (!element.inRenderedDocument())65 return false;66 if (element.styleChangeType() >= FullStyleChange)67 return false;68 if (!element.document().styleResolverIfExists())69 return false;70 return true;71 }72 73 61 inline ClassChangeInvalidation::ClassChangeInvalidation(Element& element, const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses) 74 : m_isEnabled( needsInvalidation(element))62 : m_isEnabled(element.needsStyleInvalidation()) 75 63 , m_element(element) 76 64
Note: See TracChangeset
for help on using the changeset viewer.