Title: [152512] branches/safari-537-branch

Diff

Modified: branches/safari-537-branch/LayoutTests/ChangeLog (152511 => 152512)


--- branches/safari-537-branch/LayoutTests/ChangeLog	2013-07-09 18:54:08 UTC (rev 152511)
+++ branches/safari-537-branch/LayoutTests/ChangeLog	2013-07-09 19:01:11 UTC (rev 152512)
@@ -1,5 +1,22 @@
 2013-07-09  Lucas Forschler  <[email protected]>
 
+        Merge r152453
+
+    2013-07-08  Andreas Kling  <[email protected]>
+
+            REGRESSION(r125294): A style rule with more than 8192 selectors can cause style corruption.
+            <http://webkit.org/b/118369>
+            <rdar://problem/14291428>
+
+            Reviewed by Antti Koivisto.
+
+            Added a test to document the new cap of 8192 selectors per CSS rule.
+
+            * fast/css/rule-selector-overflow-expected.txt: Added.
+            * fast/css/rule-selector-overflow.html: Added.
+
+2013-07-09  Lucas Forschler  <[email protected]>
+
         Merge r152424
 
     2013-07-05  Zalan Bujtas  <[email protected]>

Copied: branches/safari-537-branch/LayoutTests/fast/css/rule-selector-overflow-expected.txt (from rev 152453, trunk/LayoutTests/fast/css/rule-selector-overflow-expected.txt) (0 => 152512)


--- branches/safari-537-branch/LayoutTests/fast/css/rule-selector-overflow-expected.txt	                        (rev 0)
+++ branches/safari-537-branch/LayoutTests/fast/css/rule-selector-overflow-expected.txt	2013-07-09 19:01:11 UTC (rev 152512)
@@ -0,0 +1,27 @@
+This test tests and documents the behavior of CSS style rules with a massive number of selectors. Rules with >8192 selectors get split into multiple rules at the parsing stage. Setting a rule's selectorText via CSSOM will do nothing if there are more than 8192 selectors.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS rule().selectorText = selectorListWithLength(1); rule().selectorText is selectorListWithLength(1)
+PASS rule().selectorText = selectorListWithLength(8192); rule().selectorText is selectorListWithLength(8192)
+PASS rule().selectorText = '.reset'; rule().selectorText is '.reset'
+PASS rule().selectorText = selectorListWithLength(8193); rule().selectorText is '.reset'
+PASS rule().selectorText = '.reset'; rule().selectorText is '.reset'
+PASS rule().selectorText = selectorListWithLength(8193); sheet().rules.length is 1
+PASS rule().selectorText = selectorListWithLength(8192); rule().selectorText is selectorListWithLength(8192)
+PASS rule().selectorText = selectorListWithLength(8192); sheet().rules.length is 1
+PASS rule().selectorText = '.reset'; rule().selectorText is '.reset'
+PASS rule().selectorText = selectorListWithLength(8193); rule().selectorText is '.reset'
+PASS rule().selectorText = selectorListWithLength(8193); sheet().rules.length is 1
+PASS styleElement.innerText = styleSheetWithSelectorLength(1); rule().selectorText is selectorListWithLength(1)
+PASS styleElement.innerText = styleSheetWithSelectorLength(8192); rule().selectorText is selectorListWithLength(8192)
+PASS styleElement.innerText = styleSheetWithSelectorLength(8192); sheet().rules.length is 1
+PASS styleElement.innerText = styleSheetWithSelectorLength(8193); rule().selectorText is selectorListWithLength(8192)
+PASS styleElement.innerText = styleSheetWithSelectorLength(8193); sheet().rules.length is 2
+PASS styleElement.innerText = styleSheetWithSelectorLength(16384); sheet().rules.length is 2
+PASS styleElement.innerText = styleSheetWithSelectorLength(16385); sheet().rules.length is 3
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Copied: branches/safari-537-branch/LayoutTests/fast/css/rule-selector-overflow.html (from rev 152453, trunk/LayoutTests/fast/css/rule-selector-overflow.html) (0 => 152512)


--- branches/safari-537-branch/LayoutTests/fast/css/rule-selector-overflow.html	                        (rev 0)
+++ branches/safari-537-branch/LayoutTests/fast/css/rule-selector-overflow.html	2013-07-09 19:01:11 UTC (rev 152512)
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src=""
+<style id="stylebro" type="text/css">
+.peb {
+    color: red;
+}
+</style>
+</head>
+<body>
+<script>
+
+styleElement = document.getElementById("stylebro");
+
+function selectorListWithLength(length)
+{
+    var a = new Array();
+    for (i = 0; i < length; ++i)
+        a.push(".x");
+    return a.join(", ");
+}
+
+function styleSheetWithSelectorLength(length)
+{
+    return selectorListWithLength(length) + " { color: red; }";
+}
+
+function sheet()
+{
+    return styleElement.sheet;
+}
+
+function rule()
+{
+    return sheet().cssRules[0];
+}
+
+description("This test tests and documents the behavior of CSS style rules with a massive number of selectors. Rules with >8192 selectors get split into multiple rules at the parsing stage. Setting a rule's selectorText via CSSOM will do nothing if there are more than 8192 selectors.");
+
+shouldBe("rule().selectorText = selectorListWithLength(1); rule().selectorText", "selectorListWithLength(1)");
+shouldBe("rule().selectorText = selectorListWithLength(8192); rule().selectorText", "selectorListWithLength(8192)");
+shouldBe("rule().selectorText = '.reset'; rule().selectorText", "'.reset'");
+shouldBe("rule().selectorText = selectorListWithLength(8193); rule().selectorText", "'.reset'");
+shouldBe("rule().selectorText = '.reset'; rule().selectorText", "'.reset'");
+shouldBe("rule().selectorText = selectorListWithLength(8193); sheet().rules.length", "1");
+shouldBe("rule().selectorText = selectorListWithLength(8192); rule().selectorText", "selectorListWithLength(8192)");
+shouldBe("rule().selectorText = selectorListWithLength(8192); sheet().rules.length", "1");
+shouldBe("rule().selectorText = '.reset'; rule().selectorText", "'.reset'");
+shouldBe("rule().selectorText = selectorListWithLength(8193); rule().selectorText", "'.reset'");
+shouldBe("rule().selectorText = selectorListWithLength(8193); sheet().rules.length", "1");
+
+shouldBe("styleElement.innerText = styleSheetWithSelectorLength(1); rule().selectorText", "selectorListWithLength(1)");
+shouldBe("styleElement.innerText = styleSheetWithSelectorLength(8192); rule().selectorText", "selectorListWithLength(8192)");
+shouldBe("styleElement.innerText = styleSheetWithSelectorLength(8192); sheet().rules.length", "1");
+shouldBe("styleElement.innerText = styleSheetWithSelectorLength(8193); rule().selectorText", "selectorListWithLength(8192)");
+shouldBe("styleElement.innerText = styleSheetWithSelectorLength(8193); sheet().rules.length", "2");
+shouldBe("styleElement.innerText = styleSheetWithSelectorLength(16384); sheet().rules.length", "2");
+shouldBe("styleElement.innerText = styleSheetWithSelectorLength(16385); sheet().rules.length", "3");
+
+</script>
+<script src=""
+</body>
+</html>

Modified: branches/safari-537-branch/Source/WebCore/ChangeLog (152511 => 152512)


--- branches/safari-537-branch/Source/WebCore/ChangeLog	2013-07-09 18:54:08 UTC (rev 152511)
+++ branches/safari-537-branch/Source/WebCore/ChangeLog	2013-07-09 19:01:11 UTC (rev 152512)
@@ -1,5 +1,55 @@
 2013-07-09  Lucas Forschler  <[email protected]>
 
+        Merge r152453
+
+    2013-07-08  Andreas Kling  <[email protected]>
+
+            REGRESSION(r125294): A style rule with more than 8192 selectors can cause style corruption.
+            <http://webkit.org/b/118369>
+            <rdar://problem/14291428>
+
+            Reviewed by Antti Koivisto.
+
+            Add a semi-hard cap of 8192 selectors per CSS rule. Rules with longer selector lists will be split into
+            multiple rules (with 8192 selectors per rule.) The style properties are shared behind the scenes
+            so it's all pretty efficient.
+
+            This does generate a different CSSOM for gigantic selector lists, I've added a test to document this.
+            Note that setting CSSStyleRule.selectorText with over 8192 selectors will now fail, the splitting into
+            multiple rules only happens when parsing full style sheets.
+
+            Test: fast/css/rule-selector-overflow.html
+
+            * css/CSSSelectorList.cpp:
+            (WebCore::CSSSelectorList::selectorCount):
+
+                Add a helper to count the number of selectors in a list (not the number of raw selector components.)
+
+            * css/RuleSet.h:
+            * css/CSSStyleRule.cpp:
+            (WebCore::CSSStyleRule::setSelectorText):
+
+                Add RuleData::maximumSelectorCount constant and cap CSSStyleRule.selectorText to that many selectors.
+
+            * css/CSSSelectorList.h:
+            (WebCore::CSSSelectorList::adoptSelectorArray):
+            * css/StyleRule.cpp:
+            (WebCore::StyleRule::create):
+            (WebCore::StyleRule::splitIntoMultipleRulesWithMaximumSelectorCount):
+            * css/StyleRule.h:
+            (WebCore::StyleRule::parserAdoptSelectorArray):
+            * css/StyleSheetContents.cpp:
+            (WebCore::StyleSheetContents::parserAppendRule):
+
+                The meat of this change. Split rules with >8K selectors into multiple rules with 8K selectors in each.
+
+            * css/StyleRule.h:
+            (WebCore::toStyleRule):
+
+                Added a toStyleRule() helper for good measure.
+
+2013-07-09  Lucas Forschler  <[email protected]>
+
         Merge r152434
 
     2013-07-05  Tim Horton  <[email protected]>

Modified: branches/safari-537-branch/Source/WebCore/css/CSSSelectorList.cpp (152511 => 152512)


--- branches/safari-537-branch/Source/WebCore/css/CSSSelectorList.cpp	2013-07-09 18:54:08 UTC (rev 152511)
+++ branches/safari-537-branch/Source/WebCore/css/CSSSelectorList.cpp	2013-07-09 19:01:11 UTC (rev 152512)
@@ -85,6 +85,14 @@
     selectorVector.clear();
 }
 
+unsigned CSSSelectorList::selectorCount() const
+{
+    unsigned count = 0;
+    for (const CSSSelector* s = first(); s; s = next(s))
+        ++count;
+    return count;
+}
+
 unsigned CSSSelectorList::length() const
 {
     if (!m_selectorArray)

Modified: branches/safari-537-branch/Source/WebCore/css/CSSSelectorList.h (152511 => 152512)


--- branches/safari-537-branch/Source/WebCore/css/CSSSelectorList.h	2013-07-09 18:54:08 UTC (rev 152511)
+++ branches/safari-537-branch/Source/WebCore/css/CSSSelectorList.h	2013-07-09 19:01:11 UTC (rev 152512)
@@ -42,6 +42,7 @@
 
     void adopt(CSSSelectorList& list);
     void adoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectorVector);
+    void adoptSelectorArray(CSSSelector* selectors) { ASSERT(!m_selectorArray); m_selectorArray = selectors; }
 
     bool isValid() const { return !!m_selectorArray; }
     const CSSSelector* first() const { return m_selectorArray; }
@@ -63,6 +64,8 @@
 
     String selectorsText() const;
 
+    unsigned selectorCount() const;
+
 private:
     unsigned length() const;
     void deleteSelectors();

Modified: branches/safari-537-branch/Source/WebCore/css/CSSStyleRule.cpp (152511 => 152512)


--- branches/safari-537-branch/Source/WebCore/css/CSSStyleRule.cpp	2013-07-09 18:54:08 UTC (rev 152511)
+++ branches/safari-537-branch/Source/WebCore/css/CSSStyleRule.cpp	2013-07-09 19:01:11 UTC (rev 152512)
@@ -27,6 +27,7 @@
 #include "CSSStyleSheet.h"
 #include "Document.h"
 #include "PropertySetCSSStyleDeclaration.h"
+#include "RuleSet.h"
 #include "StylePropertySet.h"
 #include "StyleRule.h"
 #include <wtf/text/StringBuilder.h>
@@ -98,6 +99,10 @@
     if (!selectorList.isValid())
         return;
 
+    // NOTE: The selector list has to fit into RuleData. <http://webkit.org/b/118369>
+    if (selectorList.selectorCount() > RuleData::maximumSelectorCount)
+        return;
+
     CSSStyleSheet::RuleMutationScope mutationScope(this);
 
     m_styleRule->wrapperAdoptSelectorList(selectorList);

Modified: branches/safari-537-branch/Source/WebCore/css/RuleSet.h (152511 => 152512)


--- branches/safari-537-branch/Source/WebCore/css/RuleSet.h	2013-07-09 18:54:08 UTC (rev 152511)
+++ branches/safari-537-branch/Source/WebCore/css/RuleSet.h	2013-07-09 19:01:11 UTC (rev 152512)
@@ -55,6 +55,8 @@
 
 class RuleData {
 public:
+    static const unsigned maximumSelectorCount = 8192;
+
     RuleData(StyleRule*, unsigned selectorIndex, unsigned position, AddRuleFlags);
 
     unsigned position() const { return m_position; }

Modified: branches/safari-537-branch/Source/WebCore/css/StyleRule.cpp (152511 => 152512)


--- branches/safari-537-branch/Source/WebCore/css/StyleRule.cpp	2013-07-09 18:54:08 UTC (rev 152511)
+++ branches/safari-537-branch/Source/WebCore/css/StyleRule.cpp	2013-07-09 19:01:11 UTC (rev 152512)
@@ -260,6 +260,44 @@
     m_properties = properties;
 }
 
+PassRefPtr<StyleRule> StyleRule::create(int sourceLine, const Vector<const CSSSelector*>& selectors, PassRefPtr<StylePropertySet> properties)
+{
+    CSSSelector* selectorListArray = reinterpret_cast<CSSSelector*>(fastMalloc(sizeof(CSSSelector) * selectors.size()));
+    for (unsigned i = 0; i < selectors.size(); ++i)
+        new (NotNull, &selectorListArray[i]) CSSSelector(*selectors.at(i));
+    selectorListArray[selectors.size() - 1].setLastInSelectorList();
+    RefPtr<StyleRule> rule = StyleRule::create(sourceLine);
+    rule->parserAdoptSelectorArray(selectorListArray);
+    rule->setProperties(properties);
+    return rule.release();
+}
+
+Vector<RefPtr<StyleRule> > StyleRule::splitIntoMultipleRulesWithMaximumSelectorCount(unsigned maximumSelectorCount) const
+{
+    ASSERT(selectorList().selectorCount() > maximumSelectorCount);
+
+    Vector<RefPtr<StyleRule> > rules;
+    Vector<const CSSSelector*> selectorsToCopy;
+
+    unsigned selectorCount = 0;
+
+    for (const CSSSelector* selector = selectorList().first(); selector; selector = CSSSelectorList::next(selector)) {
+        for (const CSSSelector* component = selector; component; component = component->tagHistory())
+            selectorsToCopy.append(component);
+
+        if (++selectorCount == maximumSelectorCount) {
+            rules.append(create(sourceLine(), selectorsToCopy, m_properties));
+            selectorsToCopy.clear();
+            selectorCount = 0;
+        }
+    }
+
+    if (selectorCount)
+        rules.append(create(sourceLine(), selectorsToCopy, m_properties));
+
+    return rules;
+}
+
 StyleRulePage::StyleRulePage()
     : StyleRuleBase(Page)
 {

Modified: branches/safari-537-branch/Source/WebCore/css/StyleRule.h (152511 => 152512)


--- branches/safari-537-branch/Source/WebCore/css/StyleRule.h	2013-07-09 18:54:08 UTC (rev 152511)
+++ branches/safari-537-branch/Source/WebCore/css/StyleRule.h	2013-07-09 19:01:11 UTC (rev 152512)
@@ -127,20 +127,31 @@
     
     void parserAdoptSelectorVector(Vector<OwnPtr<CSSParserSelector> >& selectors) { m_selectorList.adoptSelectorVector(selectors); }
     void wrapperAdoptSelectorList(CSSSelectorList& selectors) { m_selectorList.adopt(selectors); }
+    void parserAdoptSelectorArray(CSSSelector* selectors) { m_selectorList.adoptSelectorArray(selectors); }
     void setProperties(PassRefPtr<StylePropertySet>);
 
     PassRefPtr<StyleRule> copy() const { return adoptRef(new StyleRule(*this)); }
 
+    Vector<RefPtr<StyleRule> > splitIntoMultipleRulesWithMaximumSelectorCount(unsigned maxSelectorCount) const;
+
     static unsigned averageSizeInBytes();
 
 private:
     StyleRule(int sourceLine);
     StyleRule(const StyleRule&);
 
+    static PassRefPtr<StyleRule> create(int sourceLine, const Vector<const CSSSelector*>&, PassRefPtr<StylePropertySet>);
+
     RefPtr<StylePropertySet> m_properties;
     CSSSelectorList m_selectorList;
 };
 
+inline const StyleRule* toStyleRule(const StyleRuleBase* rule)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!rule || rule->isStyleRule());
+    return static_cast<const StyleRule*>(rule);
+}
+
 class StyleRuleFontFace : public StyleRuleBase {
 public:
     static PassRefPtr<StyleRuleFontFace> create() { return adoptRef(new StyleRuleFontFace); }

Modified: branches/safari-537-branch/Source/WebCore/css/StyleSheetContents.cpp (152511 => 152512)


--- branches/safari-537-branch/Source/WebCore/css/StyleSheetContents.cpp	2013-07-09 18:54:08 UTC (rev 152511)
+++ branches/safari-537-branch/Source/WebCore/css/StyleSheetContents.cpp	2013-07-09 19:01:11 UTC (rev 152512)
@@ -1,6 +1,6 @@
 /*
  * (C) 1999-2003 Lars Knoll ([email protected])
- * Copyright (C) 2004, 2006, 2007, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2006, 2007, 2012, 2013 Apple Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -28,6 +28,7 @@
 #include "Document.h"
 #include "MediaList.h"
 #include "Node.h"
+#include "RuleSet.h"
 #include "SecurityOrigin.h"
 #include "StylePropertySet.h"
 #include "StyleRule.h"
@@ -140,6 +141,14 @@
         reportMediaQueryWarningIfNeeded(singleOwnerDocument(), static_cast<StyleRuleMedia*>(rule.get())->mediaQueries());
 #endif
 
+    // NOTE: The selector list has to fit into RuleData. <http://webkit.org/b/118369>
+    // If we're adding a rule with a huge number of selectors, split it up into multiple rules
+    if (rule->isStyleRule() && toStyleRule(rule.get())->selectorList().selectorCount() > RuleData::maximumSelectorCount) {
+        Vector<RefPtr<StyleRule> > rules = toStyleRule(rule.get())->splitIntoMultipleRulesWithMaximumSelectorCount(RuleData::maximumSelectorCount);
+        m_childRules.appendVector(rules);
+        return;
+    }
+
     m_childRules.append(rule);
 }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to