- Revision
- 104445
- Author
- [email protected]
- Date
- 2012-01-09 02:00:51 -0800 (Mon, 09 Jan 2012)
Log Message
Subtree invalidation on stylesheet change
https://bugs.webkit.org/show_bug.cgi?id=75834
Source/WebCore:
Reviewed by Andreas Kling.
Currently if we add a stylesheet with scoped selectors and matching scope elements exist,
we recalculate the entire document style. It is sufficient to invalidate the subtrees
matching the scope only.
This allows us to do less full style recalcs on many popular web sites (nytimes.com for example).
Subtree recalcs are typically much cheaper.
Test: fast/css/id-or-class-before-stylesheet.html
* dom/Document.cpp:
(WebCore::Document::testAddedStylesheetRequiresStyleRecalc):
(WebCore::Document::analyzeStylesheetChange):
(WebCore::Document::updateActiveStylesheets):
* dom/Document.h:
LayoutTests:
Reviewed by Andreas Kling.
* fast/css/id-or-class-before-stylesheet-expected.txt: Added.
* fast/css/id-or-class-before-stylesheet.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (104444 => 104445)
--- trunk/LayoutTests/ChangeLog 2012-01-09 09:53:28 UTC (rev 104444)
+++ trunk/LayoutTests/ChangeLog 2012-01-09 10:00:51 UTC (rev 104445)
@@ -1,3 +1,13 @@
+2012-01-09 Antti Koivisto <[email protected]>
+
+ Subtree invalidation on stylesheet change
+ https://bugs.webkit.org/show_bug.cgi?id=75834
+
+ Reviewed by Andreas Kling.
+
+ * fast/css/id-or-class-before-stylesheet-expected.txt: Added.
+ * fast/css/id-or-class-before-stylesheet.html: Added.
+
2012-01-09 Adam Barth <[email protected]>
insertAdjacentHTML doesn't play nice with DocumentFragment
Added: trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-expected.txt (0 => 104445)
--- trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-expected.txt 2012-01-09 10:00:51 UTC (rev 104445)
@@ -0,0 +1,12 @@
+Test that elements before inline stylesheets get their style updated properly
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.getComputedStyle(document.getElementById("testid")).backgroundColor is "rgb(0, 128, 0)"
+PASS window.getComputedStyle(document.getElementsByClassName("testclass")[0]).backgroundColor is "rgb(0, 128, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+id test
+class test
Added: trunk/LayoutTests/fast/css/id-or-class-before-stylesheet.html (0 => 104445)
--- trunk/LayoutTests/fast/css/id-or-class-before-stylesheet.html (rev 0)
+++ trunk/LayoutTests/fast/css/id-or-class-before-stylesheet.html 2012-01-09 10:00:51 UTC (rev 104445)
@@ -0,0 +1,24 @@
+<html lang=en>
+<head>
+<script src=""
+<style>
+#testid { background-color: red; }
+.testclass { background-color: red; }
+</style>
+</head>
+<body>
+<div id=testid>id test</div>
+<style>
+#testid { background-color: green }
+</style>
+<div class=testclass>class test</div>
+<style>
+.testclass { background-color: green; }
+</style>
+<script>
+description("Test that elements before inline stylesheets get their style updated properly");
+shouldBe('window.getComputedStyle(document.getElementById("testid")).backgroundColor','"rgb(0, 128, 0)"');
+shouldBe('window.getComputedStyle(document.getElementsByClassName("testclass")[0]).backgroundColor','"rgb(0, 128, 0)"');
+</script>
+<script src=""
+</body>
Modified: trunk/Source/WebCore/ChangeLog (104444 => 104445)
--- trunk/Source/WebCore/ChangeLog 2012-01-09 09:53:28 UTC (rev 104444)
+++ trunk/Source/WebCore/ChangeLog 2012-01-09 10:00:51 UTC (rev 104445)
@@ -1,3 +1,25 @@
+2012-01-09 Antti Koivisto <[email protected]>
+
+ Subtree invalidation on stylesheet change
+ https://bugs.webkit.org/show_bug.cgi?id=75834
+
+ Reviewed by Andreas Kling.
+
+ Currently if we add a stylesheet with scoped selectors and matching scope elements exist,
+ we recalculate the entire document style. It is sufficient to invalidate the subtrees
+ matching the scope only.
+
+ This allows us to do less full style recalcs on many popular web sites (nytimes.com for example).
+ Subtree recalcs are typically much cheaper.
+
+ Test: fast/css/id-or-class-before-stylesheet.html
+
+ * dom/Document.cpp:
+ (WebCore::Document::testAddedStylesheetRequiresStyleRecalc):
+ (WebCore::Document::analyzeStylesheetChange):
+ (WebCore::Document::updateActiveStylesheets):
+ * dom/Document.h:
+
2012-01-09 Carlos Garcia Campos <[email protected]>
Unreviewed. Fix make distcheck issues.
Modified: trunk/Source/WebCore/dom/Document.cpp (104444 => 104445)
--- trunk/Source/WebCore/dom/Document.cpp 2012-01-09 09:53:28 UTC (rev 104444)
+++ trunk/Source/WebCore/dom/Document.cpp 2012-01-09 10:00:51 UTC (rev 104445)
@@ -3161,22 +3161,29 @@
return true;
HashSet<AtomicStringImpl*>::iterator end = idScopes.end();
for (HashSet<AtomicStringImpl*>::iterator it = idScopes.begin(); it != end; ++it) {
- if (hasElementWithId(*it))
+ AtomicStringImpl* id = *it;
+ Element* idElement = getElementById(id);
+ if (!idElement)
+ continue;
+ if (containsMultipleElementsWithId(id))
return true;
+ idElement->setNeedsStyleRecalc();
}
end = classScopes.end();
for (HashSet<AtomicStringImpl*>::iterator it = classScopes.begin(); it != end; ++it) {
// FIXME: getElementsByClassName is not optimal for this. We should handle all classes in a single pass.
- if (getElementsByClassName(*it)->length())
- return true;
+ RefPtr<NodeList> classElements = getElementsByClassName(*it);
+ unsigned elementCount = classElements->length();
+ for (unsigned i = 0; i < elementCount; ++i)
+ classElements->item(i)->setNeedsStyleRecalc();
}
return false;
}
-void Document::analyzeStylesheetChange(StyleSelectorUpdateFlag updateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, bool& requiresStyleSelectorReset, bool& requiresStyleRecalc)
+void Document::analyzeStylesheetChange(StyleSelectorUpdateFlag updateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, bool& requiresStyleSelectorReset, bool& requiresFullStyleRecalc)
{
requiresStyleSelectorReset = true;
- requiresStyleRecalc = true;
+ requiresFullStyleRecalc = true;
// Stylesheets of <style> elements that @import stylesheets are active but loading. We need to trigger a full recalc when such loads are done.
bool hasActiveLoadingStylesheet = false;
@@ -3215,7 +3222,7 @@
if (testAddedStylesheetRequiresStyleRecalc(static_cast<CSSStyleSheet*>(newStylesheets[i].get())))
return;
}
- requiresStyleRecalc = false;
+ requiresFullStyleRecalc = false;
}
bool Document::updateActiveStylesheets(StyleSelectorUpdateFlag updateFlag)
@@ -3235,8 +3242,8 @@
collectActiveStylesheets(newStylesheets);
bool requiresStyleSelectorReset;
- bool requiresStyleRecalc;
- analyzeStylesheetChange(updateFlag, newStylesheets, requiresStyleSelectorReset, requiresStyleRecalc);
+ bool requiresFullStyleRecalc;
+ analyzeStylesheetChange(updateFlag, newStylesheets, requiresStyleSelectorReset, requiresFullStyleRecalc);
if (requiresStyleSelectorReset)
m_styleSelector.clear();
@@ -3249,7 +3256,7 @@
m_didCalculateStyleSelector = true;
m_hasDirtyStyleSelector = false;
- return requiresStyleRecalc;
+ return requiresFullStyleRecalc;
}
void Document::setHoverNode(PassRefPtr<Node> newHoverNode)
Modified: trunk/Source/WebCore/dom/Document.h (104444 => 104445)
--- trunk/Source/WebCore/dom/Document.h 2012-01-09 09:53:28 UTC (rev 104444)
+++ trunk/Source/WebCore/dom/Document.h 2012-01-09 10:00:51 UTC (rev 104445)
@@ -1162,7 +1162,7 @@
bool updateActiveStylesheets(StyleSelectorUpdateFlag);
void collectActiveStylesheets(Vector<RefPtr<StyleSheet> >&);
bool testAddedStylesheetRequiresStyleRecalc(CSSStyleSheet*);
- void analyzeStylesheetChange(StyleSelectorUpdateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, bool& requiresStyleSelectorReset, bool& requiresStyleRecalc);
+ void analyzeStylesheetChange(StyleSelectorUpdateFlag, const Vector<RefPtr<StyleSheet> >& newStylesheets, bool& requiresStyleSelectorReset, bool& requiresFullStyleRecalc);
void deleteCustomFonts();