Diff
Modified: trunk/LayoutTests/ChangeLog (114264 => 114265)
--- trunk/LayoutTests/ChangeLog 2012-04-16 15:56:42 UTC (rev 114264)
+++ trunk/LayoutTests/ChangeLog 2012-04-16 16:37:10 UTC (rev 114265)
@@ -1,3 +1,17 @@
+2012-04-15 Antti Koivisto <an...@apple.com>
+
+ REGRESSION (r104445): Style is not recomputed on serenaandlily.com
+ https://bugs.webkit.org/show_bug.cgi?id=83663
+
+ Reviewed by Andreas Kling.
+
+ Update the existing test with case insensitive comparisons and add a strict mode test.
+
+ * fast/css/id-or-class-before-stylesheet-expected.txt:
+ * fast/css/id-or-class-before-stylesheet-strict-expected.txt: Added.
+ * fast/css/id-or-class-before-stylesheet-strict.html: Added.
+ * fast/css/id-or-class-before-stylesheet.html:
+
2012-04-16 Zalan Bujtas <zbuj...@gmail.com>
[Qt] LayoutTest: Replace setTimeout with synchronous layout for frame flattening where possible.
Modified: trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-expected.txt (114264 => 114265)
--- trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-expected.txt 2012-04-16 15:56:42 UTC (rev 114264)
+++ trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-expected.txt 2012-04-16 16:37:10 UTC (rev 114265)
@@ -5,8 +5,12 @@
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 window.getComputedStyle(document.getElementById("testID2")).backgroundColor is "rgb(0, 128, 0)"
+PASS window.getComputedStyle(document.getElementsByClassName("testClass2")[0]).backgroundColor is "rgb(0, 128, 0)"
PASS successfullyParsed is true
TEST COMPLETE
id test
class test
+case insensitive id test
+case insensitive class test
Added: trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-strict-expected.txt (0 => 114265)
--- trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-strict-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-strict-expected.txt 2012-04-16 16:37:10 UTC (rev 114265)
@@ -0,0 +1,16 @@
+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 window.getComputedStyle(document.getElementById("testID2")).backgroundColor is "rgb(255, 0, 0)"
+PASS window.getComputedStyle(document.getElementsByClassName("testClass2")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+id test
+class test
+case insensitive id test
+case insensitive class test
Added: trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-strict.html (0 => 114265)
--- trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-strict.html (rev 0)
+++ trunk/LayoutTests/fast/css/id-or-class-before-stylesheet-strict.html 2012-04-16 16:37:10 UTC (rev 114265)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html lang=en>
+<head>
+<script src=""
+<style>
+#testid { background-color: red; }
+#testID2 { background-color: red; }
+.testclass { background-color: red; }
+.testClass2 { 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>
+<div id=testID2>case insensitive id test</div>
+<style>
+#TESTid2 { background-color: green }
+</style>
+<div class=testClass2>case insensitive class test</div>
+<style>
+.TESTclass2 { 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)"');
+shouldBe('window.getComputedStyle(document.getElementById("testID2")).backgroundColor','"rgb(255, 0, 0)"');
+shouldBe('window.getComputedStyle(document.getElementsByClassName("testClass2")[0]).backgroundColor','"rgb(255, 0, 0)"');
+</script>
+<script src=""
+</body>
Modified: trunk/LayoutTests/fast/css/id-or-class-before-stylesheet.html (114264 => 114265)
--- trunk/LayoutTests/fast/css/id-or-class-before-stylesheet.html 2012-04-16 15:56:42 UTC (rev 114264)
+++ trunk/LayoutTests/fast/css/id-or-class-before-stylesheet.html 2012-04-16 16:37:10 UTC (rev 114265)
@@ -3,7 +3,9 @@
<script src=""
<style>
#testid { background-color: red; }
+#testID2 { background-color: red; }
.testclass { background-color: red; }
+.testClass2 { background-color: red; }
</style>
</head>
<body>
@@ -15,10 +17,20 @@
<style>
.testclass { background-color: green; }
</style>
+<div id=testID2>case insensitive id test</div>
+<style>
+#TESTid2 { background-color: green }
+</style>
+<div class=testClass2>case insensitive class test</div>
+<style>
+.TESTclass2 { 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)"');
+shouldBe('window.getComputedStyle(document.getElementById("testID2")).backgroundColor','"rgb(0, 128, 0)"');
+shouldBe('window.getComputedStyle(document.getElementsByClassName("testClass2")[0]).backgroundColor','"rgb(0, 128, 0)"');
</script>
<script src=""
</body>
Modified: trunk/Source/WebCore/ChangeLog (114264 => 114265)
--- trunk/Source/WebCore/ChangeLog 2012-04-16 15:56:42 UTC (rev 114264)
+++ trunk/Source/WebCore/ChangeLog 2012-04-16 16:37:10 UTC (rev 114265)
@@ -1,3 +1,32 @@
+2012-04-16 Antti Koivisto <an...@apple.com>
+
+ REGRESSION (r104445): Style is not recomputed on serenaandlily.com
+ https://bugs.webkit.org/show_bug.cgi?id=83663
+
+ Reviewed by Andreas Kling.
+
+ CSS class and id selectors are case insensitive in non-strict modes. The code
+ that invalidated the scope elements used getElementByID() which is case
+ sensitive in all modes. As a result we would fail to invalidate elements
+ that would match a style rule but used different case in id.
+
+ The new code invalidates by crawling the DOM tree. This often (when there are classes)
+ actually faster than the existing code as we can now handle everything in a single pass.
+ Each class scope required a crawl with the old code.
+
+ The code uses the same functions as the selector matching code to get the same behavior.
+
+ The maximum class limit is lifted as number of classes does not affect complexity anymore.
+
+ Test: fast/css/id-or-class-before-stylesheet-strict.html
+
+ * css/SelectorChecker.h:
+ (WebCore::SelectorChecker::elementMatchesSelectorScopes):
+ (WebCore):
+ * dom/Document.cpp:
+ (WebCore::Document::testAddedStylesheetRequiresStyleRecalc):
+ (WebCore):
+
2012-04-16 Uday Kiran <udayki...@motorola.com>
CSS3 Selectors failures on css3test.com
Modified: trunk/Source/WebCore/css/SelectorChecker.h (114264 => 114265)
--- trunk/Source/WebCore/css/SelectorChecker.h 2012-04-16 15:56:42 UTC (rev 114264)
+++ trunk/Source/WebCore/css/SelectorChecker.h 2012-04-16 16:37:10 UTC (rev 114265)
@@ -30,10 +30,11 @@
#include "Attribute.h"
#include "CSSSelector.h"
-#include "Element.h"
#include "InspectorInstrumentation.h"
#include "LinkHash.h"
#include "RenderStyleConstants.h"
+#include "SpaceSplitString.h"
+#include "StyledElement.h"
#include <wtf/BloomFilter.h>
#include <wtf/HashSet.h>
#include <wtf/Vector.h>
@@ -116,6 +117,7 @@
// Find the ids or classes selectors are scoped to. The selectors only apply to elements in subtrees where the root element matches the scope.
static bool determineSelectorScopes(const CSSSelectorList&, HashSet<AtomicStringImpl*>& idScopes, HashSet<AtomicStringImpl*>& classScopes);
+ static bool elementMatchesSelectorScopes(const StyledElement*, const HashSet<AtomicStringImpl*>& idScopes, const HashSet<AtomicStringImpl*>& classScopes);
private:
bool checkOneSelector(const SelectorCheckingContext&, PseudoId&) const;
@@ -226,6 +228,20 @@
return true;
}
+inline bool SelectorChecker::elementMatchesSelectorScopes(const StyledElement* element, const HashSet<AtomicStringImpl*>& idScopes, const HashSet<AtomicStringImpl*>& classScopes)
+{
+ if (!idScopes.isEmpty() && element->hasID() && idScopes.contains(element->idForStyleResolution().impl()))
+ return true;
+ if (classScopes.isEmpty() || !element->hasClass())
+ return false;
+ const SpaceSplitString& classNames = element->classNames();
+ for (unsigned i = 0; i < classNames.size(); ++i) {
+ if (classScopes.contains(classNames[i].impl()))
+ return true;
+ }
+ return false;
}
+}
+
#endif
Modified: trunk/Source/WebCore/dom/Document.cpp (114264 => 114265)
--- trunk/Source/WebCore/dom/Document.cpp 2012-04-16 15:56:42 UTC (rev 114264)
+++ trunk/Source/WebCore/dom/Document.cpp 2012-04-16 16:37:10 UTC (rev 114265)
@@ -3333,36 +3333,29 @@
{
// See if all rules on the sheet are scoped to some specific ids or classes.
// Then test if we actually have any of those in the tree at the moment.
- // FIXME: Even we if we find some, we could just invalidate those subtrees instead of invalidating the entire style.
HashSet<AtomicStringImpl*> idScopes;
HashSet<AtomicStringImpl*> classScopes;
if (!CSSStyleSelector::determineStylesheetSelectorScopes(stylesheet, idScopes, classScopes))
return true;
- // Testing for classes is not particularly fast so bail out if there are more than a few.
- static const int maximumClassScopesToTest = 4;
- if (classScopes.size() > maximumClassScopesToTest)
- return true;
- HashSet<AtomicStringImpl*>::iterator end = idScopes.end();
- for (HashSet<AtomicStringImpl*>::iterator it = idScopes.begin(); it != end; ++it) {
- AtomicStringImpl* id = *it;
- Element* idElement = getElementById(id);
- if (!idElement)
+ // Invalidate the subtrees that match the scopes.
+ Node* node = firstChild();
+ while (node) {
+ if (!node->isStyledElement()) {
+ node = node->traverseNextNode();
continue;
- if (containsMultipleElementsWithId(id))
- return true;
- idElement->setNeedsStyleRecalc();
+ }
+ StyledElement* element = static_cast<StyledElement*>(node);
+ if (SelectorChecker::elementMatchesSelectorScopes(element, idScopes, classScopes)) {
+ element->setNeedsStyleRecalc();
+ // The whole subtree is now invalidated, we can skip to the next sibling.
+ node = node->traverseNextSibling();
+ continue;
+ }
+ node = node->traverseNextNode();
}
- 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.
- 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& requiresFullStyleRecalc)
{
requiresStyleSelectorReset = true;