Diff
Modified: trunk/LayoutTests/ChangeLog (196635 => 196636)
--- trunk/LayoutTests/ChangeLog 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/LayoutTests/ChangeLog 2016-02-16 17:24:01 UTC (rev 196636)
@@ -1,3 +1,13 @@
+2016-02-16 Antti Koivisto <[email protected]>
+
+ Factor id mutation style invalidation code into a class
+ https://bugs.webkit.org/show_bug.cgi?id=154287
+
+ Reviewed by Andreas Kling.
+
+ * fast/css/style-invalidation-id-change-descendants-expected.txt: Added.
+ * fast/css/style-invalidation-id-change-descendants.html: Added.
+
2016-02-16 Ryan Haddad <[email protected]>
Rebaseline imported/w3c/web-platform-tests/html/dom/interfaces.html for ios-simulator after r196621
Modified: trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants-expected.txt (196635 => 196636)
--- trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants-expected.txt 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants-expected.txt 2016-02-16 17:24:01 UTC (rev 196636)
@@ -1,4 +1,4 @@
-Test that we invalidate the element subtree minimally on class attribute change
+Test that we invalidate the element subtree minimally on attribute change
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
Modified: trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants.html (196635 => 196636)
--- trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants.html 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/LayoutTests/fast/css/style-invalidation-attribute-change-descendants.html 2016-02-16 17:24:01 UTC (rev 196636)
@@ -76,7 +76,7 @@
</body>
<script>
-description('Test that we invalidate the element subtree minimally on class attribute change');
+description('Test that we invalidate the element subtree minimally on attribute change');
function testStyleChangeType(tag, type)
{
Added: trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants-expected.txt (0 => 196636)
--- trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants-expected.txt 2016-02-16 17:24:01 UTC (rev 196636)
@@ -0,0 +1,56 @@
+Test basic style invalidation optimization on id mutation
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS hasExpectedStyle is true
+NoStyleChange
+NoStyleChange
+PASS testStyleChangeType("root", "NoStyleChange") is true
+Setting id NotThere
+NoStyleChange
+NoStyleChange
+PASS testStyleChangeType("root", "NoStyleChange") is true
+Setting id id1
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType("root", "FullStyleChange") is true
+PASS hasExpectedStyle is true
+Setting id id2
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType("root", "FullStyleChange") is true
+PASS hasExpectedStyle is true
+Setting id id1
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType("root", "FullStyleChange") is true
+PASS hasExpectedStyle is true
+Setting id id3
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType("root", "FullStyleChange") is true
+PASS hasExpectedStyle is true
+Setting id id4
+InlineStyleChange
+InlineStyleChange
+PASS testStyleChangeType("root", "InlineStyleChange") is true
+PASS hasExpectedStyle is true
+Setting id id4
+NoStyleChange
+NoStyleChange
+PASS testStyleChangeType("root", "NoStyleChange") is true
+PASS hasExpectedStyle is true
+Setting id NotThere
+InlineStyleChange
+InlineStyleChange
+PASS testStyleChangeType("root", "InlineStyleChange") is true
+Setting id id1
+FullStyleChange
+FullStyleChange
+PASS testStyleChangeType("root", "FullStyleChange") is true
+PASS hasExpectedStyle is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants.html (0 => 196636)
--- trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants.html (rev 0)
+++ trunk/LayoutTests/fast/css/style-invalidation-id-change-descendants.html 2016-02-16 17:24:01 UTC (rev 196636)
@@ -0,0 +1,137 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<style>
+* {
+ color: black;
+}
+#id1 target {
+ color: rgb(1, 1, 1);
+}
+
+#id2 > inert target {
+ color: rgb(2, 2, 2);
+}
+
+#id3 {
+ color: rgb(3, 3, 3);
+}
+
+#id4 {
+ color: rgb(4, 4, 4);
+}
+
+
+</style>
+</head>
+<body>
+ <root>
+ <!-- With renderer -->
+ <inert>
+ <inert>
+ <inert></inert>
+ <target>
+ <inert></inert>
+ <target></target>
+ </target>
+ </inert>
+ <target></target>
+ <inert></inert>
+ </inert>
+ </root>
+ <root style="display:none;">
+ <!-- Without renderer -->
+ <inert>
+ <inert>
+ <inert></inert>
+ <target>
+ <inert></inert>
+ <target></target>
+ </target>
+ </inert>
+ <target></target>
+ <inert></inert>
+ </inert>
+ </root>
+</body>
+<script>
+
+description('Test basic style invalidation optimization on id mutation');
+
+function testStyleChangeType(tag, type)
+{
+ var elements = document.querySelectorAll(tag);
+ for (var i = 0; i < elements.length; ++i) {
+ debug(window.internals.styleChangeType(elements[i]));
+ if (window.internals.styleChangeType(elements[i]) != type)
+ return false;
+ }
+ return true;
+}
+
+function testStyleInvalidation(expectedDescendantStyleChange) {
+ shouldBeTrue('testStyleChangeType("root", "' + expectedDescendantStyleChange +'")');
+}
+
+function setId(name) {
+ debug("Setting id " + name);
+ var allRoots = document.querySelectorAll("root");
+ allRoots[0].id = name;
+ allRoots[1].id = name
+}
+
+function checkStyle(n) {
+ document.documentElement.offsetTop;
+
+ hasExpectedStyle = true;
+ expectedColor = 'rgb('+n+', '+n+', '+n+')';
+ var targets = document.querySelectorAll("target");
+ for (var i = 0; i < targets.length; ++i) {
+ hasExpectedStyle = getComputedStyle(targets[i]).color == expectedColor;
+ if (!hasExpectedStyle)
+ break;
+ }
+ shouldBeTrue("hasExpectedStyle");
+}
+
+checkStyle(0);
+testStyleInvalidation("NoStyleChange");
+
+setId('NotThere');
+testStyleInvalidation("NoStyleChange");
+
+setId('id1');
+testStyleInvalidation("FullStyleChange");
+checkStyle(1);
+
+setId('id2');
+testStyleInvalidation("FullStyleChange");
+checkStyle(2);
+
+setId('id1');
+testStyleInvalidation("FullStyleChange");
+checkStyle(1);
+
+setId('id3');
+testStyleInvalidation("FullStyleChange");
+checkStyle(0);
+
+setId('id4');
+testStyleInvalidation("InlineStyleChange");
+checkStyle(0);
+
+setId('id4');
+testStyleInvalidation("NoStyleChange");
+checkStyle(0);
+
+setId('NotThere');
+testStyleInvalidation("InlineStyleChange");
+
+setId('id1');
+testStyleInvalidation("FullStyleChange");
+checkStyle(1);
+
+</script>
+<script src=""
+</html>
Modified: trunk/Source/WebCore/CMakeLists.txt (196635 => 196636)
--- trunk/Source/WebCore/CMakeLists.txt 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/CMakeLists.txt 2016-02-16 17:24:01 UTC (rev 196636)
@@ -2632,6 +2632,7 @@
style/AttributeChangeInvalidation.cpp
style/ClassChangeInvalidation.cpp
+ style/IdChangeInvalidation.cpp
style/InlineTextBoxStyle.cpp
style/RenderTreePosition.cpp
style/StyleChange.cpp
Modified: trunk/Source/WebCore/ChangeLog (196635 => 196636)
--- trunk/Source/WebCore/ChangeLog 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/ChangeLog 2016-02-16 17:24:01 UTC (rev 196636)
@@ -1,3 +1,36 @@
+2016-02-16 Antti Koivisto <[email protected]>
+
+ Factor id mutation style invalidation code into a class
+ https://bugs.webkit.org/show_bug.cgi?id=154287
+
+ Reviewed by Andreas Kling.
+
+ Also add a cheap basic optimization that avoids descendant invalidation if they can not be affected.
+
+ It would be easy to implement fine grained invalidation like with classes and attribute selectors.
+ However dynamic id changes are not common enough (nor recommended) to pay the memory cost of
+ the required data structures.
+
+ Test: fast/css/style-invalidation-id-change-descendants.html
+
+ * CMakeLists.txt:
+ * WebCore.vcxproj/WebCore.vcxproj:
+ * WebCore.xcodeproj/project.pbxproj:
+ * css/RuleFeature.cpp:
+ (WebCore::RuleFeatureSet::recursivelyCollectFeaturesFromSelector):
+ (WebCore::RuleFeatureSet::add):
+ (WebCore::RuleFeatureSet::clear):
+ * css/RuleFeature.h:
+ * dom/Element.cpp:
+ (WebCore::makeIdForStyleResolution):
+ (WebCore::Element::attributeChanged):
+ (WebCore::checkNeedsStyleInvalidationForIdChange): Deleted.
+ * style/IdChangeInvalidation.cpp: Added.
+ (WebCore::Style::IdChangeInvalidation::invalidateStyle):
+ * style/IdChangeInvalidation.h: Added.
+ (WebCore::Style::IdChangeInvalidation::IdChangeInvalidation):
+ (WebCore::Style::IdChangeInvalidation::~IdChangeInvalidation):
+
2016-02-16 Andreas Kling <[email protected]>
Drop StyleResolver and SelectorQueryCache when entering PageCache.
Modified: trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj (196635 => 196636)
--- trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/WebCore.vcxproj/WebCore.vcxproj 2016-02-16 17:24:01 UTC (rev 196636)
@@ -19297,6 +19297,7 @@
<ClCompile Include="..\storage\StorageNamespaceProvider.cpp" />
<ClCompile Include="..\style\AttributeChangeInvalidation.cpp" />
<ClCompile Include="..\style\ClassChangeInvalidation.cpp" />
+ <ClCompile Include="..\style\IdChangeInvalidation.cpp" />
<ClCompile Include="..\style\InlineTextBoxStyle.cpp" />
<ClCompile Include="..\style\RenderTreePosition.cpp" />
<ClCompile Include="..\style\StyleChange.cpp" />
@@ -22868,6 +22869,7 @@
<ClInclude Include="..\storage\StorageNamespaceProvider.h" />
<ClInclude Include="..\style\AttributeChangeInvalidation.h" />
<ClInclude Include="..\style\ClassChangeInvalidation.h" />
+ <ClInclude Include="..\style\IdChangeInvalidation.h" />
<ClInclude Include="..\style\InlineTextBoxStyle.h" />
<ClInclude Include="..\style\RenderTreePosition.h" />
<ClInclude Include="..\style\StyleChange.h" />
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (196635 => 196636)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2016-02-16 17:24:01 UTC (rev 196636)
@@ -6639,6 +6639,8 @@
E4A814D61C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */; };
E4A814D81C70E10500BF85AC /* AttributeChangeInvalidation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A814D71C70E10500BF85AC /* AttributeChangeInvalidation.cpp */; };
E4A814DA1C70E10D00BF85AC /* AttributeChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */; };
+ E4A814DE1C7338D100BF85AC /* IdChangeInvalidation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E4A814DD1C7338D100BF85AC /* IdChangeInvalidation.cpp */; };
+ E4A814E01C7338EB00BF85AC /* IdChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */; };
E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1517D1BB950009FB31 /* ElementIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4AE7C1A17D232350009FB31 /* ElementAncestorIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
E4AFCFA50DAF29A300F5F55C /* UnitBezier.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */; };
@@ -10548,8 +10550,8 @@
83D26D3D1AFDCC50001B3873 /* ParentNode.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = ParentNode.idl; sourceTree = "<group>"; };
83D35AEA1C7187ED00F70D5A /* XMLHttpRequestEventTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XMLHttpRequestEventTarget.h; sourceTree = "<group>"; };
83D35AEB1C7187ED00F70D5A /* XMLHttpRequestEventTarget.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = XMLHttpRequestEventTarget.idl; sourceTree = "<group>"; };
- 83D35AEF1C718D8400F70D5A /* JSXMLHttpRequestEventTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JSXMLHttpRequestEventTarget.cpp; path = JSXMLHttpRequestEventTarget.cpp; sourceTree = "<group>"; };
- 83D35AF01C718D8400F70D5A /* JSXMLHttpRequestEventTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSXMLHttpRequestEventTarget.h; path = JSXMLHttpRequestEventTarget.h; sourceTree = "<group>"; };
+ 83D35AEF1C718D8400F70D5A /* JSXMLHttpRequestEventTarget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSXMLHttpRequestEventTarget.cpp; sourceTree = "<group>"; };
+ 83D35AF01C718D8400F70D5A /* JSXMLHttpRequestEventTarget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSXMLHttpRequestEventTarget.h; sourceTree = "<group>"; };
83E359A01BB1031D002CEB98 /* JSHTMLTimeElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSHTMLTimeElement.h; sourceTree = "<group>"; };
83E359A11BB1031D002CEB98 /* JSHTMLTimeElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSHTMLTimeElement.cpp; sourceTree = "<group>"; };
83E959E11B8BC22B004D9385 /* NativeNodeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeNodeFilter.h; sourceTree = "<group>"; };
@@ -14647,6 +14649,8 @@
E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClassChangeInvalidation.cpp; sourceTree = "<group>"; };
E4A814D71C70E10500BF85AC /* AttributeChangeInvalidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AttributeChangeInvalidation.cpp; sourceTree = "<group>"; };
E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AttributeChangeInvalidation.h; sourceTree = "<group>"; };
+ E4A814DD1C7338D100BF85AC /* IdChangeInvalidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IdChangeInvalidation.cpp; sourceTree = "<group>"; };
+ E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdChangeInvalidation.h; sourceTree = "<group>"; };
E4AE7C1517D1BB950009FB31 /* ElementIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIterator.h; sourceTree = "<group>"; };
E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementAncestorIterator.h; sourceTree = "<group>"; };
E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnitBezier.h; sourceTree = "<group>"; };
@@ -23441,6 +23445,8 @@
E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */,
E4A814D51C6DEE8D00BF85AC /* ClassChangeInvalidation.cpp */,
E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */,
+ E4A814DD1C7338D100BF85AC /* IdChangeInvalidation.cpp */,
+ E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */,
1C0106FE192594DF008A4201 /* InlineTextBoxStyle.cpp */,
1C0106FF192594DF008A4201 /* InlineTextBoxStyle.h */,
5824ABA81AE849C8009074B7 /* RenderTreePosition.cpp */,
@@ -27866,6 +27872,7 @@
9393E605151A9A1800066F06 /* StyleCachedImageSet.h in Headers */,
E401E0A41C3C0B8300F34D10 /* StyleChange.h in Headers */,
9DAC7C571AF2CB6400437C44 /* StyleContentAlignmentData.h in Headers */,
+ E4A814E01C7338EB00BF85AC /* IdChangeInvalidation.h in Headers */,
BC779E171BB227CA00CAA8BF /* StyleCustomPropertyData.h in Headers */,
BC5EB67F0E81D4A700B25965 /* StyleDashboardRegion.h in Headers */,
A8C4A7FD09D563270003AC8D /* StyledElement.h in Headers */,
@@ -30487,6 +30494,7 @@
B2FA3D5A0AB75A6F000E5AC4 /* JSSVGClipPathElement.cpp in Sources */,
B2FA3D5C0AB75A6F000E5AC4 /* JSSVGColor.cpp in Sources */,
B2FA3D5E0AB75A6F000E5AC4 /* JSSVGComponentTransferFunctionElement.cpp in Sources */,
+ E4A814DE1C7338D100BF85AC /* IdChangeInvalidation.cpp in Sources */,
B2FA3D600AB75A6F000E5AC4 /* JSSVGCursorElement.cpp in Sources */,
B2FA3D620AB75A6F000E5AC4 /* JSSVGDefsElement.cpp in Sources */,
B2FA3D640AB75A6F000E5AC4 /* JSSVGDescElement.cpp in Sources */,
Modified: trunk/Source/WebCore/css/RuleFeature.cpp (196635 => 196636)
--- trunk/Source/WebCore/css/RuleFeature.cpp 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/css/RuleFeature.cpp 2016-02-16 17:24:01 UTC (rev 196636)
@@ -39,9 +39,11 @@
{
const CSSSelector* selector = &firstSelector;
do {
- if (selector->match() == CSSSelector::Id)
+ if (selector->match() == CSSSelector::Id) {
idsInRules.add(selector->value().impl());
- else if (selector->match() == CSSSelector::Class) {
+ if (matchesAncestor)
+ idsMatchingAncestorsInRules.add(selector->value().impl());
+ } else if (selector->match() == CSSSelector::Class) {
classesInRules.add(selector->value().impl());
if (matchesAncestor)
selectorFeatures.classesMatchingAncestors.append(selector->value().impl());
@@ -118,6 +120,7 @@
void RuleFeatureSet::add(const RuleFeatureSet& other)
{
idsInRules.add(other.idsInRules.begin(), other.idsInRules.end());
+ idsMatchingAncestorsInRules.add(other.idsMatchingAncestorsInRules.begin(), other.idsMatchingAncestorsInRules.end());
classesInRules.add(other.classesInRules.begin(), other.classesInRules.end());
attributeCanonicalLocalNamesInRules.add(other.attributeCanonicalLocalNamesInRules.begin(), other.attributeCanonicalLocalNamesInRules.end());
attributeLocalNamesInRules.add(other.attributeLocalNamesInRules.begin(), other.attributeLocalNamesInRules.end());
@@ -146,6 +149,7 @@
void RuleFeatureSet::clear()
{
idsInRules.clear();
+ idsMatchingAncestorsInRules.clear();
classesInRules.clear();
attributeCanonicalLocalNamesInRules.clear();
attributeLocalNamesInRules.clear();
Modified: trunk/Source/WebCore/css/RuleFeature.h (196635 => 196636)
--- trunk/Source/WebCore/css/RuleFeature.h 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/css/RuleFeature.h 2016-02-16 17:24:01 UTC (rev 196636)
@@ -52,6 +52,7 @@
void collectFeatures(const RuleData&);
HashSet<AtomicStringImpl*> idsInRules;
+ HashSet<AtomicStringImpl*> idsMatchingAncestorsInRules;
HashSet<AtomicStringImpl*> classesInRules;
HashSet<AtomicStringImpl*> attributeCanonicalLocalNamesInRules;
HashSet<AtomicStringImpl*> attributeLocalNamesInRules;
Modified: trunk/Source/WebCore/dom/Element.cpp (196635 => 196636)
--- trunk/Source/WebCore/dom/Element.cpp 2016-02-16 17:12:26 UTC (rev 196635)
+++ trunk/Source/WebCore/dom/Element.cpp 2016-02-16 17:24:01 UTC (rev 196636)
@@ -57,6 +57,7 @@
#include "HTMLParserIdioms.h"
#include "HTMLSelectElement.h"
#include "HTMLTemplateElement.h"
+#include "IdChangeInvalidation.h"
#include "IdTargetObserverRegistry.h"
#include "KeyboardEvent.h"
#include "MainFrame.h"
@@ -1216,25 +1217,10 @@
return value;
}
-static bool checkNeedsStyleInvalidationForIdChange(const AtomicString& oldId, const AtomicString& newId, StyleResolver* styleResolver)
-{
- ASSERT(newId != oldId);
- if (!oldId.isEmpty() && styleResolver->hasSelectorForId(oldId))
- return true;
- if (!newId.isEmpty() && styleResolver->hasSelectorForId(newId))
- return true;
- return false;
-}
-
void Element::attributeChanged(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue, AttributeModificationReason)
{
bool valueIsSameAsBefore = oldValue == newValue;
- StyleResolver* styleResolver = document().styleResolverIfExists();
- bool testShouldInvalidateStyle = inRenderedDocument() && styleResolver && styleChangeType() < FullStyleChange;
-
- bool shouldInvalidateStyle = false;
-
if (!valueIsSameAsBefore) {
if (name == HTMLNames::idAttr) {
if (!oldValue.isEmpty())
@@ -1245,15 +1231,17 @@
AtomicString oldId = elementData()->idForStyleResolution();
AtomicString newId = makeIdForStyleResolution(newValue, document().inQuirksMode());
if (newId != oldId) {
+ Style::IdChangeInvalidation styleInvalidation(*this, oldId, newId);
elementData()->setIdForStyleResolution(newId);
- shouldInvalidateStyle = testShouldInvalidateStyle && checkNeedsStyleInvalidationForIdChange(oldId, newId, styleResolver);
}
} else if (name == classAttr)
classAttributeChanged(newValue);
else if (name == HTMLNames::nameAttr)
elementData()->setHasNameAttribute(!newValue.isNull());
- else if (name == HTMLNames::pseudoAttr)
- shouldInvalidateStyle |= testShouldInvalidateStyle && isInShadowTree();
+ else if (name == HTMLNames::pseudoAttr) {
+ if (needsStyleInvalidation() && isInShadowTree())
+ setNeedsStyleRecalc(FullStyleChange);
+ }
#if ENABLE(SHADOW_DOM) || ENABLE(DETAILS_ELEMENT)
else if (name == HTMLNames::slotAttr) {
if (auto* parent = parentElement()) {
@@ -1273,9 +1261,6 @@
invalidateNodeListAndCollectionCachesInAncestors(&name, this);
- if (shouldInvalidateStyle)
- setNeedsStyleRecalc();
-
if (AXObjectCache* cache = document().existingAXObjectCache())
cache->handleAttributeChanged(name, this);
}
Added: trunk/Source/WebCore/style/IdChangeInvalidation.cpp (0 => 196636)
--- trunk/Source/WebCore/style/IdChangeInvalidation.cpp (rev 0)
+++ trunk/Source/WebCore/style/IdChangeInvalidation.cpp 2016-02-16 17:24:01 UTC (rev 196636)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "IdChangeInvalidation.h"
+
+#include "DocumentRuleSets.h"
+#include "ElementChildIterator.h"
+#include "StyleResolver.h"
+
+namespace WebCore {
+namespace Style {
+
+void IdChangeInvalidation::invalidateStyle(const AtomicString& changedId)
+{
+ if (changedId.isEmpty())
+ return;
+
+ auto& ruleSets = m_element.styleResolver().ruleSets();
+
+ bool mayAffectStyle = ruleSets.features().idsInRules.contains(changedId.impl());
+ if (!mayAffectStyle)
+ return;
+
+ if (m_element.shadowRoot() && ruleSets.authorStyle()->hasShadowPseudoElementRules()) {
+ m_element.setNeedsStyleRecalc(FullStyleChange);
+ return;
+ }
+
+ m_element.setNeedsStyleRecalc(InlineStyleChange);
+
+ // This could be easily optimized for fine-grained descendant invalidation similar to ClassChangeInvalidation.
+ // However using ids for dynamic styling is rare and this is probably not worth the memory cost of the required data structures.
+ bool mayAffectDescendantStyle = ruleSets.features().idsMatchingAncestorsInRules.contains(changedId.impl());
+ if (mayAffectDescendantStyle)
+ m_element.setNeedsStyleRecalc(FullStyleChange);
+ else
+ m_element.setNeedsStyleRecalc(InlineStyleChange);
+}
+
+}
+}
Added: trunk/Source/WebCore/style/IdChangeInvalidation.h (0 => 196636)
--- trunk/Source/WebCore/style/IdChangeInvalidation.h (rev 0)
+++ trunk/Source/WebCore/style/IdChangeInvalidation.h 2016-02-16 17:24:01 UTC (rev 196636)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IdChangeInvalidation_h
+#define IdChangeInvalidation_h
+
+#include "Element.h"
+
+namespace WebCore {
+
+namespace Style {
+
+class IdChangeInvalidation {
+public:
+ IdChangeInvalidation(Element&, const AtomicString& oldId, const AtomicString& newId);
+ ~IdChangeInvalidation();
+
+private:
+ void invalidateStyle(const AtomicString&);
+
+ const bool m_isEnabled;
+ Element& m_element;
+
+ AtomicString m_newId;
+};
+
+inline IdChangeInvalidation::IdChangeInvalidation(Element& element, const AtomicString& oldId, const AtomicString& newId)
+ : m_isEnabled(element.needsStyleInvalidation())
+ , m_element(element)
+{
+ if (!m_isEnabled)
+ return;
+ if (oldId == newId)
+ return;
+ m_newId = newId;
+ invalidateStyle(oldId);
+}
+
+inline IdChangeInvalidation::~IdChangeInvalidation()
+{
+ if (!m_isEnabled)
+ return;
+ invalidateStyle(m_newId);
+}
+
+}
+}
+
+#endif
+