Diff
Modified: trunk/LayoutTests/ChangeLog (134366 => 134367)
--- trunk/LayoutTests/ChangeLog 2012-11-13 06:36:48 UTC (rev 134366)
+++ trunk/LayoutTests/ChangeLog 2012-11-13 06:50:15 UTC (rev 134367)
@@ -1,3 +1,25 @@
+2012-11-12 Shinya Kawanaka <[email protected]>
+
+ Changing id, className, or attribute should invalidate distribution
+ https://bugs.webkit.org/show_bug.cgi?id=100738
+
+ Reviewed by Dimitri Glazkov.
+
+ We have test cases that id/class/attribute is changed, and thier reprojection cases.
+
+ * fast/dom/shadow/distribution-attribute-modified-expected.html: Added.
+ * fast/dom/shadow/distribution-attribute-modified.html: Added.
+ * fast/dom/shadow/distribution-className-modified-expected.html: Added.
+ * fast/dom/shadow/distribution-className-modified.html: Added.
+ * fast/dom/shadow/distribution-id-modified-expected.html: Added.
+ * fast/dom/shadow/distribution-id-modified.html: Added.
+ * fast/dom/shadow/reprojection-attribute-modified-expected.html: Added.
+ * fast/dom/shadow/reprojection-attribute-modified.html: Added.
+ * fast/dom/shadow/reprojection-className-modified-expected.html: Added.
+ * fast/dom/shadow/reprojection-className-modified.html: Added.
+ * fast/dom/shadow/reprojection-id-modified-expected.html: Added.
+ * fast/dom/shadow/reprojection-id-modified.html: Added.
+
2012-11-10 Dirk Schulze <[email protected]>
BasicShapes 'circle', 'rectangle', 'ellipse' should be animatable with themselves
Added: trunk/LayoutTests/fast/dom/shadow/distribution-attribute-modified-expected.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/distribution-attribute-modified-expected.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/distribution-attribute-modified-expected.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<div id="host">
+ <div>F</div>
+</div>
+
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/distribution-attribute-modified.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/distribution-attribute-modified.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/distribution-attribute-modified.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<script src=""
+
+<div id="host">
+ <div>A</div>
+ <div>B</div>
+ <div>C</div>
+ <div>D</div>
+ <div>E</div>
+ <div id="F">F</div>
+</div>
+
+<script>
+if (window.testRunner)
+ testRunner.waitUntilDone();
+
+var shadowRoot = new WebKitShadowRoot(host);
+shadowRoot.innerHTML = '<content select="div[title]"></content>';
+
+setTimeout(function() {
+ F.title = 'something';
+ if (window.testRunner)
+ testRunner.notifyDone();
+}, 0);
+</script>
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/distribution-className-modified-expected.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/distribution-className-modified-expected.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/distribution-className-modified-expected.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<div id="host">
+ <div>A</div>
+ <div>D</div>
+ <div>F</div>
+</div>
+
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/distribution-className-modified.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/distribution-className-modified.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/distribution-className-modified.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<script src=""
+
+<div id="host">
+ <div class="selected">A</div>
+ <div>B</div>
+ <div>C</div>
+ <div class="selected">D</div>
+ <div>E</div>
+ <div id="F">F</div>
+</div>
+
+<script>
+if (window.testRunner)
+ testRunner.waitUntilDone();
+
+var shadowRoot = new WebKitShadowRoot(host);
+shadowRoot.innerHTML = '<content select=".selected"></content>';
+
+setTimeout(function() {
+ F.className = 'selected';
+ if (window.testRunner)
+ testRunner.notifyDone();
+}, 0);
+</script>
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/distribution-id-modified-expected.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/distribution-id-modified-expected.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/distribution-id-modified-expected.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<div id="host">
+ <div>F</div>
+</div>
+
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/distribution-id-modified.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/distribution-id-modified.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/distribution-id-modified.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<script src=""
+
+<div id="host">
+ <div id="selected">A</div>
+ <div>B</div>
+ <div>C</div>
+ <div>D</div>
+ <div>E</div>
+ <div id="F">F</div>
+</div>
+
+<script>
+if (window.testRunner)
+ testRunner.waitUntilDone();
+
+var shadowRoot = new WebKitShadowRoot(host);
+shadowRoot.innerHTML = '<content select="#selected"></content>';
+
+setTimeout(function() {
+ A = selected;
+ F.id = 'selected';
+ A.id = '';
+ if (window.testRunner)
+ testRunner.notifyDone();
+}, 0);
+</script>
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/reprojection-attribute-modified-expected.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/reprojection-attribute-modified-expected.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/reprojection-attribute-modified-expected.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<div id="host"><div>
+ <div>F</div>
+</div></div>
+
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/reprojection-attribute-modified.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/reprojection-attribute-modified.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/reprojection-attribute-modified.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<script src=""
+
+<div id="host1">
+ <div>A</div>
+ <div>B</div>
+ <div>C</div>
+ <div>D</div>
+ <div>E</div>
+ <div id="F">F</div>
+</div>
+
+<script>
+if (window.testRunner)
+ testRunner.waitUntilDone();
+
+var shadowRoot1 = new WebKitShadowRoot(host1);
+shadowRoot1.innerHTML = '<div id="host2"><shadow></shadow></div>';
+
+var host2 = shadowRoot1.getElementById('host2');
+var shadowRoot2 = new WebKitShadowRoot(host2);
+shadowRoot2.innerHTML = '<content select="div[title=selected]"></content>';
+
+setTimeout(function() {
+ F.title = 'selected';
+ if (window.testRunner)
+ testRunner.notifyDone();
+}, 0);
+</script>
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/reprojection-className-modified-expected.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/reprojection-className-modified-expected.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/reprojection-className-modified-expected.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<div id="host"><div>
+ <div>A</div>
+ <div>D</div>
+ <div>F</div>
+</div></div>
+
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/reprojection-className-modified.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/reprojection-className-modified.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/reprojection-className-modified.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<script src=""
+
+<div id="host1">
+ <div class="selected">A</div>
+ <div>B</div>
+ <div>C</div>
+ <div class="selected">D</div>
+ <div>E</div>
+ <div id="F">F</div>
+</div>
+
+<script>
+if (window.testRunner)
+ testRunner.waitUntilDone();
+
+var shadowRoot1 = new WebKitShadowRoot(host1);
+shadowRoot1.innerHTML = '<div id="host2"><shadow></shadow></div>';
+
+var host2 = shadowRoot1.getElementById('host2');
+var shadowRoot2 = new WebKitShadowRoot(host2);
+shadowRoot2.innerHTML = '<content select=".selected"></content>';
+
+setTimeout(function() {
+ F.className = 'selected';
+ if (window.testRunner)
+ testRunner.notifyDone();
+}, 0);
+</script>
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/reprojection-id-modified-expected.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/reprojection-id-modified-expected.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/reprojection-id-modified-expected.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<div id="host"><div>
+ <div>F</div>
+</div></div>
+
+</html>
Added: trunk/LayoutTests/fast/dom/shadow/reprojection-id-modified.html (0 => 134367)
--- trunk/LayoutTests/fast/dom/shadow/reprojection-id-modified.html (rev 0)
+++ trunk/LayoutTests/fast/dom/shadow/reprojection-id-modified.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+
+<html>
+<body>
+
+<script src=""
+
+<div id="host1">
+ <div id="selected">A</div>
+ <div>B</div>
+ <div>C</div>
+ <div>D</div>
+ <div>E</div>
+ <div id="F">F</div>
+</div>
+
+<script>
+if (window.testRunner)
+ testRunner.waitUntilDone();
+
+var shadowRoot1 = new WebKitShadowRoot(host1);
+shadowRoot1.innerHTML = '<div id="host2"><shadow></shadow></div>';
+
+var host2 = shadowRoot1.getElementById('host2');
+var shadowRoot2 = new WebKitShadowRoot(host2);
+shadowRoot2.innerHTML = '<content select="#selected"></content>';
+
+setTimeout(function() {
+ A = selected;
+ A.id = '';
+ F.id = 'selected';
+ if (window.testRunner)
+ testRunner.notifyDone();
+}, 0);
+</script>
+</html>
Modified: trunk/PerformanceTests/ChangeLog (134366 => 134367)
--- trunk/PerformanceTests/ChangeLog 2012-11-13 06:36:48 UTC (rev 134366)
+++ trunk/PerformanceTests/ChangeLog 2012-11-13 06:50:15 UTC (rev 134367)
@@ -1,3 +1,19 @@
+2012-11-12 Shinya Kawanaka <[email protected]>
+
+ Changing id, className, or attribute should invalidate distribution
+ https://bugs.webkit.org/show_bug.cgi?id=100738
+
+ Reviewed by Dimitri Glazkov.
+
+ Added test code to modify id/class/attribute.
+
+ * DOM/ModifyAttribute.html: Added.
+ * DOM/resources/dom-perf/modify-attribute.js: Added.
+ (ModifyAttribute.CreateElementToSetUp):
+ (ModifyAttribute.ModifyId):
+ (ModifyAttribute.ModifyClass):
+ (ModifyAttribute.ModifyTitle):
+
2012-11-06 Adam Barth <[email protected]>
DOMImplementation should use ScriptWrappable
Added: trunk/PerformanceTests/DOM/ModifyAttribute.html (0 => 134367)
--- trunk/PerformanceTests/DOM/ModifyAttribute.html (rev 0)
+++ trunk/PerformanceTests/DOM/ModifyAttribute.html 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<body>
+<div id="container"><span id="benchmark_content"></span></div>
+<script type="text/_javascript_" src=""
+<script type="text/_javascript_" src=""
+<script type="text/_javascript_" src=""
+<script>runBenchmarkSuite(ModifyAttributeTest);</script>
+</body>
+</html>
Added: trunk/PerformanceTests/DOM/resources/dom-perf/modify-attribute.js (0 => 134367)
--- trunk/PerformanceTests/DOM/resources/dom-perf/modify-attribute.js (rev 0)
+++ trunk/PerformanceTests/DOM/resources/dom-perf/modify-attribute.js 2012-11-13 06:50:15 UTC (rev 134367)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 Google 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:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * 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.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER OR 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.
+ */
+
+// ModifyAttribute - measure attribute modification performance
+
+var ModifyAttribute = {};
+var nLoops = 100000;
+
+ModifyAttribute.CreateElementToSetUp = function() {
+ return document.createElement('div');
+}
+
+ModifyAttribute.ModifyId = function(element) {
+ var nLoops = window.nLoops;
+ var idValue1 = 'id1';
+ var idValue2 = 'id2';
+
+ for (var i = 0; i < nLoops; ++i) {
+ element.id = idValue1;
+ element.id = idValue2;
+ }
+}
+
+ModifyAttribute.ModifyClass = function(element) {
+ var nLoops = window.nLoops;
+ var className1 = 'class1';
+ var className2 = 'class2';
+
+ for (var i = 0; i < nLoops; ++i) {
+ element.className = className1;
+ element.className = className2;
+ }
+}
+
+ModifyAttribute.ModifyTitle = function(element) {
+ var nLoops = window.nLoops;
+ var title1 = 'title1';
+ var title2 = 'title2';
+
+ for (var i = 0; i < nLoops; ++i) {
+ element.title = title1;
+ element.title = title2;
+ }
+}
+
+var ModifyAttributeTest = new BenchmarkSuite('ModifyAttribute', [
+ new Benchmark("Modify id", ModifyAttribute.ModifyId, ModifyAttribute.CreateElementToSetUp),
+ new Benchmark("Modify class", ModifyAttribute.ModifyClass, ModifyAttribute.CreateElementToSetUp),
+ new Benchmark("Modify title", ModifyAttribute.ModifyTitle, ModifyAttribute.CreateElementToSetUp)
+]);
Modified: trunk/Source/WebCore/ChangeLog (134366 => 134367)
--- trunk/Source/WebCore/ChangeLog 2012-11-13 06:36:48 UTC (rev 134366)
+++ trunk/Source/WebCore/ChangeLog 2012-11-13 06:50:15 UTC (rev 134367)
@@ -1,3 +1,54 @@
+2012-11-12 Shinya Kawanaka <[email protected]>
+
+ Changing id, className, or attribute should invalidate distribution
+ https://bugs.webkit.org/show_bug.cgi?id=100738
+
+ Reviewed by Dimitri Glazkov.
+
+ When id, className, or attribute is changed, we might have to invalidate distribution.
+ However, we don't want to do useless invalidation. So we consult with the RuleFeatureSet of ElementShadow,
+ and invalidate distribution only if necessary.
+
+ When className is changed, we can share a lot of code between invalidating distribution and invalidating style.
+ So we made checkNeedsStyleInvalidationForClassChange a template method, and share it.
+
+ Also we've measured how this patch makes changing attribute slow. By converting checkNeedsStyleInvalidationForClassChange
+ to template, actually this improves the performance of changing attribute code. I've measured each code 3 times.
+
+ DOM/ModifyAttribute.html
+ Before this patch:
+ median stdev min max [ms]
+ 1st 115.62 0.67 114.75 117.00
+ 2nd 115.08 1.13 113.25 117.58
+ 3rd 114.75 1.16 113.42 117.83
+
+ After this patch:
+ median stdev min max [ms]
+ 1st 102.55 0.95 101.25 104.50
+ 2nd 103.10 0.86 102.20 100.95
+ 3rd 103.30 1.05 102.10 106.65
+
+ Tests: fast/dom/shadow/distribution-attribute-modified.html
+ fast/dom/shadow/distribution-className-modified.html
+ fast/dom/shadow/distribution-id-modified.html
+ fast/dom/shadow/reprojection-attribute-modified.html
+ fast/dom/shadow/reprojection-className-modified.html
+ fast/dom/shadow/reprojection-id-modified.html
+
+ * dom/Element.cpp:
+ (WebCore::Element::attributeChanged):
+ (WebCore::HasSelectorForClassStyleFunctor::HasSelectorForClassStyleFunctor):
+ (HasSelectorForClassStyleFunctor):
+ (WebCore::HasSelectorForClassStyleFunctor::operator()): Returns true if StyleResolver::hasSelectorForClass returns true.
+ (WebCore):
+ (WebCore::HasSelectorForClassDistributionFunctor::HasSelectorForClassDistributionFunctor):
+ (HasSelectorForClassDistributionFunctor):
+ (WebCore::HasSelectorForClassDistributionFunctor::operator()): Returns true if ElementShadow::hasSelectorForClass returns true.
+ (WebCore::checkFunctorForClassChange):
+ (WebCore::checkNeedsStyleInvalidationForClassChange): Extacted the implementation to checkFunctorForClassChange.
+ (WebCore::checkNeedsDistributionInvalidationForClassChange):
+ (WebCore::Element::classAttributeChanged):
+
2012-11-12 Joe Mason <[email protected]>
[BlackBerry] NetworkJob should not check if data is received with HEAD
Modified: trunk/Source/WebCore/dom/Element.cpp (134366 => 134367)
--- trunk/Source/WebCore/dom/Element.cpp 2012-11-13 06:36:48 UTC (rev 134366)
+++ trunk/Source/WebCore/dom/Element.cpp 2012-11-13 06:50:15 UTC (rev 134367)
@@ -53,6 +53,7 @@
#include "HTMLOptionsCollection.h"
#include "HTMLParserIdioms.h"
#include "HTMLTableRowsCollection.h"
+#include "InsertionPoint.h"
#include "InspectorInstrumentation.h"
#include "MutationObserverInterestGroup.h"
#include "MutationRecord.h"
@@ -763,8 +764,13 @@
document()->incDOMTreeVersion();
StyleResolver* styleResolver = document()->styleResolverIfExists();
+ ElementShadow* elementShadow = shadowOfParentForDistribution(this);
+ if (elementShadow)
+ elementShadow->ensureSelectFeatureSetCollected();
+
bool testShouldInvalidateStyle = attached() && styleResolver && styleChangeType() < FullStyleChange;
bool shouldInvalidateStyle = false;
+ bool shouldInvalidateDistribution = false;
if (isIdAttributeName(name)) {
AtomicString oldId = attributeData()->idForStyleResolution();
@@ -772,6 +778,8 @@
if (newId != oldId) {
attributeData()->setIdForStyleResolution(newId);
shouldInvalidateStyle = testShouldInvalidateStyle && checkNeedsStyleInvalidationForIdChange(oldId, newId, styleResolver);
+ shouldInvalidateDistribution |= elementShadow && !oldId.isEmpty() && elementShadow->selectRuleFeatureSet().hasSelectorForId(oldId);
+ shouldInvalidateDistribution |= elementShadow && !newId.isEmpty() && elementShadow->selectRuleFeatureSet().hasSelectorForId(newId);
}
} else if (name == HTMLNames::nameAttr)
setHasName(!newValue.isNull());
@@ -779,12 +787,15 @@
shouldInvalidateStyle |= testShouldInvalidateStyle && isInShadowTree();
shouldInvalidateStyle |= testShouldInvalidateStyle && styleResolver->hasSelectorForAttribute(name.localName());
+ shouldInvalidateDistribution |= elementShadow && elementShadow->selectRuleFeatureSet().hasSelectorForAttribute(name.localName());
invalidateNodeListCachesInAncestors(&name, this);
if (shouldInvalidateStyle)
setNeedsStyleRecalc();
-
+ if (shouldInvalidateDistribution)
+ elementShadow->invalidateDistribution();
+
if (AXObjectCache::accessibilityEnabled())
document()->axObjectCache()->handleAttributeChanged(name, this);
}
@@ -822,21 +833,49 @@
return classStringHasClassName(newClassString.characters16(), length);
}
-static bool checkNeedsStyleInvalidationForClassChange(const SpaceSplitString& changedClasses, StyleResolver* styleResolver)
+struct HasSelectorForClassStyleFunctor {
+ explicit HasSelectorForClassStyleFunctor(StyleResolver* resolver)
+ : styleResolver(resolver)
+ { }
+
+ bool operator()(const AtomicString& className) const
+ {
+ return styleResolver->hasSelectorForClass(className);
+ }
+
+ StyleResolver* styleResolver;
+};
+
+struct HasSelectorForClassDistributionFunctor {
+ explicit HasSelectorForClassDistributionFunctor(ElementShadow* elementShadow)
+ : elementShadow(elementShadow)
+ { }
+
+ bool operator()(const AtomicString& className) const
+ {
+ return elementShadow->selectRuleFeatureSet().hasSelectorForClass(className);
+ }
+
+ ElementShadow* elementShadow;
+};
+
+template<typename Functor>
+static bool checkFunctorForClassChange(const SpaceSplitString& changedClasses, Functor functor)
{
unsigned changedSize = changedClasses.size();
for (unsigned i = 0; i < changedSize; ++i) {
- if (styleResolver->hasSelectorForClass(changedClasses[i]))
+ if (functor(changedClasses[i]))
return true;
}
return false;
}
-static bool checkNeedsStyleInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, StyleResolver* styleResolver)
+template<typename Functor>
+static bool checkFunctorForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, Functor functor)
{
unsigned oldSize = oldClasses.size();
if (!oldSize)
- return checkNeedsStyleInvalidationForClassChange(newClasses, styleResolver);
+ return checkFunctorForClassChange(newClasses, functor);
BitVector remainingClassBits;
remainingClassBits.ensureSize(oldSize);
// Class vectors tend to be very short. This is faster than using a hash table.
@@ -848,25 +887,50 @@
continue;
}
}
- if (styleResolver->hasSelectorForClass(newClasses[i]))
+ if (functor(newClasses[i]))
return true;
}
for (unsigned i = 0; i < oldSize; ++i) {
// If the bit is not set the the corresponding class has been removed.
if (remainingClassBits.quickGet(i))
continue;
- if (styleResolver->hasSelectorForClass(oldClasses[i]))
+ if (functor(oldClasses[i]))
return true;
}
return false;
}
+static inline bool checkNeedsStyleInvalidationForClassChange(const SpaceSplitString& changedClasses, StyleResolver* styleResolver)
+{
+ return checkFunctorForClassChange(changedClasses, HasSelectorForClassStyleFunctor(styleResolver));
+}
+
+static inline bool checkNeedsStyleInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, StyleResolver* styleResolver)
+{
+ return checkFunctorForClassChange(oldClasses, newClasses, HasSelectorForClassStyleFunctor(styleResolver));
+}
+
+static inline bool checkNeedsDistributionInvalidationForClassChange(const SpaceSplitString& changedClasses, ElementShadow* elementShadow)
+{
+ return checkFunctorForClassChange(changedClasses, HasSelectorForClassDistributionFunctor(elementShadow));
+}
+
+static inline bool checkNeedsDistributionInvalidationForClassChange(const SpaceSplitString& oldClasses, const SpaceSplitString& newClasses, ElementShadow* elementShadow)
+{
+ return checkFunctorForClassChange(oldClasses, newClasses, HasSelectorForClassDistributionFunctor(elementShadow));
+}
+
void Element::classAttributeChanged(const AtomicString& newClassString)
{
StyleResolver* styleResolver = document()->styleResolverIfExists();
bool testShouldInvalidateStyle = attached() && styleResolver && styleChangeType() < FullStyleChange;
bool shouldInvalidateStyle = false;
+ ElementShadow* elementShadow = shadowOfParentForDistribution(this);
+ if (elementShadow)
+ elementShadow->ensureSelectFeatureSetCollected();
+ bool shouldInvalidateDistribution = false;
+
if (classStringHasClassName(newClassString)) {
const ElementAttributeData* attributeData = ensureAttributeData();
const bool shouldFoldCase = document()->inQuirksMode();
@@ -876,10 +940,11 @@
const SpaceSplitString& newClasses = attributeData->classNames();
shouldInvalidateStyle = testShouldInvalidateStyle && checkNeedsStyleInvalidationForClassChange(oldClasses, newClasses, styleResolver);
+ shouldInvalidateDistribution = elementShadow && checkNeedsDistributionInvalidationForClassChange(oldClasses, newClasses, elementShadow);
} else if (const ElementAttributeData* attributeData = this->attributeData()) {
const SpaceSplitString& oldClasses = attributeData->classNames();
shouldInvalidateStyle = testShouldInvalidateStyle && checkNeedsStyleInvalidationForClassChange(oldClasses, styleResolver);
-
+ shouldInvalidateDistribution = elementShadow && checkNeedsDistributionInvalidationForClassChange(oldClasses, elementShadow);
attributeData->clearClass();
}
@@ -888,6 +953,8 @@
if (shouldInvalidateStyle)
setNeedsStyleRecalc();
+ if (shouldInvalidateDistribution)
+ elementShadow->invalidateDistribution();
}
// Returns true is the given attribute is an event handler.