Title: [112382] trunk/Source/WebCore
Revision
112382
Author
[email protected]
Date
2012-03-28 03:41:18 -0700 (Wed, 28 Mar 2012)

Log Message

Separate @import rules from other rules in CSSStyleSheet
https://bugs.webkit.org/show_bug.cgi?id=82384 

Reviewed by Andreas Kling.

Import rules always come before all other rules (except @charset). They currently live 
in the generic child rule vector. They can be moved to a vector of their own for stronger
typing and more focused traversal. This will also make future refactoring easier.
        
- @import rules go to m_importRules
- the rest go to m_childRules
        
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::collectMatchingRulesForList):
* css/CSSStyleSheet.cpp:
(WebCore::CSSStyleSheet::parserAppendRule):
(WebCore::CSSStyleSheet::length):
(WebCore::CSSStyleSheet::item):
(WebCore::CSSStyleSheet::clearRules):
(WebCore::CSSStyleSheet::rules):
(WebCore::CSSStyleSheet::insertRule):
(WebCore::CSSStyleSheet::deleteRule):
(WebCore::CSSStyleSheet::isLoading):
(WebCore::CSSStyleSheet::addSubresourceStyleURLs):
* css/CSSStyleSheet.h:
(WebCore):
(CSSStyleSheet):
(WebCore::CSSStyleSheet::childRules):
(WebCore::CSSStyleSheet::importRules):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (112381 => 112382)


--- trunk/Source/WebCore/ChangeLog	2012-03-28 10:10:14 UTC (rev 112381)
+++ trunk/Source/WebCore/ChangeLog	2012-03-28 10:41:18 UTC (rev 112382)
@@ -1,3 +1,35 @@
+2012-03-27  Antti Koivisto  <[email protected]>
+
+        Separate @import rules from other rules in CSSStyleSheet
+        https://bugs.webkit.org/show_bug.cgi?id=82384 
+
+        Reviewed by Andreas Kling.
+
+        Import rules always come before all other rules (except @charset). They currently live 
+        in the generic child rule vector. They can be moved to a vector of their own for stronger
+        typing and more focused traversal. This will also make future refactoring easier.
+        
+        - @import rules go to m_importRules
+        - the rest go to m_childRules
+        
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::collectMatchingRulesForList):
+        * css/CSSStyleSheet.cpp:
+        (WebCore::CSSStyleSheet::parserAppendRule):
+        (WebCore::CSSStyleSheet::length):
+        (WebCore::CSSStyleSheet::item):
+        (WebCore::CSSStyleSheet::clearRules):
+        (WebCore::CSSStyleSheet::rules):
+        (WebCore::CSSStyleSheet::insertRule):
+        (WebCore::CSSStyleSheet::deleteRule):
+        (WebCore::CSSStyleSheet::isLoading):
+        (WebCore::CSSStyleSheet::addSubresourceStyleURLs):
+        * css/CSSStyleSheet.h:
+        (WebCore):
+        (CSSStyleSheet):
+        (WebCore::CSSStyleSheet::childRules):
+        (WebCore::CSSStyleSheet::importRules):
+
 2012-03-28  Pavel Feldman  <[email protected]>
 
         Web Inspector: REGRESSION: Stack overflow on the page with > 100kloc

Modified: trunk/Source/WebCore/css/CSSStyleSelector.cpp (112381 => 112382)


--- trunk/Source/WebCore/css/CSSStyleSelector.cpp	2012-03-28 10:10:14 UTC (rev 112381)
+++ trunk/Source/WebCore/css/CSSStyleSelector.cpp	2012-03-28 10:41:18 UTC (rev 112382)
@@ -2225,7 +2225,15 @@
 {
     ASSERT(!stylesheet->isLoading());
 
-    const Vector<RefPtr<CSSRule> >& rules = stylesheet->ruleVector();
+    const Vector<RefPtr<CSSImportRule> >& importRules = stylesheet->importRules();
+    for (unsigned i = 0; i < importRules.size(); ++i) {
+        if (!importRules[i]->styleSheet())
+            continue;
+        if (!determineStylesheetSelectorScopes(importRules[i]->styleSheet(), idScopes, classScopes))
+            return false;
+    }
+
+    const Vector<RefPtr<CSSRule> >& rules = stylesheet->childRules();
     for (unsigned i = 0; i < rules.size(); i++) {
         CSSRule* rule = rules[i].get();
         if (rule->isStyleRule()) {
@@ -2234,14 +2242,6 @@
                 return false;
             continue;
         } 
-        if (rule->isImportRule()) {
-            CSSImportRule* importRule = static_cast<CSSImportRule*>(rule);
-            if (importRule->styleSheet()) {
-                if (!determineStylesheetSelectorScopes(importRule->styleSheet(), idScopes, classScopes))
-                    return false;
-            }
-            continue;
-        }
         // FIXME: Media rules and maybe some others could be allowed.
         return false;
     }
@@ -2453,19 +2453,23 @@
     // contain our current medium
     if (sheet->mediaQueries() && !medium.eval(sheet->mediaQueries(), styleSelector))
         return; // the style sheet doesn't apply
+    
+    const Vector<RefPtr<CSSImportRule> >& importRules = sheet->importRules();
+    for (unsigned i = 0; i < importRules.size(); ++i) {
+        CSSImportRule* importRule = importRules[i].get();
+        if (importRule->styleSheet() && (!importRule->mediaQueries() || medium.eval(importRule->mediaQueries(), styleSelector)))
+            addRulesFromSheet(importRule->styleSheet(), medium, styleSelector, scope);
+    }
 
-    const Vector<RefPtr<CSSRule> >& rules = sheet->ruleVector();
+    const Vector<RefPtr<CSSRule> >& rules = sheet->childRules();
     for (unsigned i = 0; i < rules.size(); ++i) {
         CSSRule* rule = rules[i].get();
+
+        ASSERT(!rule->isImportRule());
         if (rule->isStyleRule())
             addStyleRule(static_cast<CSSStyleRule*>(rule)->styleRule(), !scope);
         else if (rule->isPageRule())
             addPageRule(static_cast<CSSPageRule*>(rule));
-        else if (rule->isImportRule()) {
-            CSSImportRule* import = static_cast<CSSImportRule*>(rule);
-            if (import->styleSheet() && (!import->mediaQueries() || medium.eval(import->mediaQueries(), styleSelector)))
-                addRulesFromSheet(import->styleSheet(), medium, styleSelector, scope);
-        }
         else if (rule->isMediaRule()) {
             CSSMediaRule* mediaRule = static_cast<CSSMediaRule*>(rule);
 

Modified: trunk/Source/WebCore/css/CSSStyleSheet.cpp (112381 => 112382)


--- trunk/Source/WebCore/css/CSSStyleSheet.cpp	2012-03-28 10:10:14 UTC (rev 112381)
+++ trunk/Source/WebCore/css/CSSStyleSheet.cpp	2012-03-28 10:41:18 UTC (rev 112382)
@@ -102,13 +102,17 @@
     clearRules();
 }
 
-void CSSStyleSheet::parserAppendRule(PassRefPtr<CSSRule> child)
+void CSSStyleSheet::parserAppendRule(PassRefPtr<CSSRule> rule)
 {
-    ASSERT(!child->isCharsetRule());
-    CSSRule* c = child.get();
-    m_children.append(child);
-    if (c->isImportRule())
-        static_cast<CSSImportRule*>(c)->requestStyleSheet();
+    ASSERT(!rule->isCharsetRule());
+    if (rule->isImportRule()) {
+        // Parser enforces that @import rules come before anything else except @charset.
+        ASSERT(m_childRules.isEmpty());
+        m_importRules.append(static_cast<CSSImportRule*>(rule.get()));
+        m_importRules.last()->requestStyleSheet();
+        return;
+    }
+    m_childRules.append(rule);
 }
 
 CSSCharsetRule* CSSStyleSheet::ensureCharsetRule()
@@ -123,7 +127,8 @@
 {
     unsigned result = 0;
     result += hasCharsetRule() ? 1 : 0;
-    result += m_children.size();
+    result += m_importRules.size();
+    result += m_childRules.size();
     return result;
 }
 
@@ -135,7 +140,12 @@
             return ensureCharsetRule();
         --childVectorIndex;
     }
-    return childVectorIndex < m_children.size() ? m_children[childVectorIndex].get() : 0; 
+    if (childVectorIndex < m_importRules.size())
+        return m_importRules[childVectorIndex].get();
+
+    childVectorIndex -= m_importRules.size();
+
+    return childVectorIndex < m_childRules.size() ? m_childRules[childVectorIndex].get() : 0; 
 }
 
 void CSSStyleSheet::clearCharsetRule()
@@ -152,11 +162,18 @@
     // For style rules outside the document, .parentStyleSheet can become null even if the style rule
     // is still observable from _javascript_. This matches the behavior of .parentNode for nodes, but
     // it's not ideal because it makes the CSSOM's behavior depend on the timing of garbage collection.
-    for (unsigned i = 0; i < m_children.size(); ++i) {
-        ASSERT(m_children.at(i)->parentStyleSheet() == this);
-        m_children.at(i)->setParentStyleSheet(0);
+    for (unsigned i = 0; i < m_childRules.size(); ++i) {
+        ASSERT(m_childRules[i]->parentStyleSheet() == this);
+        m_childRules[i]->setParentStyleSheet(0);
     }
-    m_children.clear();
+    m_childRules.clear();
+
+    for (unsigned i = 0; i < m_importRules.size(); ++i) {
+        ASSERT(m_importRules.at(i)->parentStyleSheet() == this);
+        m_importRules[i]->setParentStyleSheet(0);
+    }
+    m_importRules.clear();
+
     clearCharsetRule();
 }
 
@@ -175,11 +192,12 @@
         return 0;
     // IE behavior.
     RefPtr<StaticCSSRuleList> nonCharsetRules = StaticCSSRuleList::create();
-    nonCharsetRules->rules().append(m_children);
+    nonCharsetRules->rules().append(m_importRules.data(), m_importRules.size());
+    nonCharsetRules->rules().append(m_childRules.data(), m_childRules.size());
     return nonCharsetRules.release();
 }
 
-unsigned CSSStyleSheet::insertRule(const String& rule, unsigned index, ExceptionCode& ec)
+unsigned CSSStyleSheet::insertRule(const String& ruleString, unsigned index, ExceptionCode& ec)
 {
     ec = 0;
     if (index > length()) {
@@ -187,17 +205,17 @@
         return 0;
     }
     CSSParser p(useStrictParsing());
-    RefPtr<CSSRule> r = p.parseRule(this, rule);
+    RefPtr<CSSRule> rule = p.parseRule(this, ruleString);
 
-    if (!r) {
+    if (!rule) {
         ec = SYNTAX_ERR;
         return 0;
     }
     // Parser::parseRule doesn't currently allow @charset so we don't need to deal with it.
-    ASSERT(!r->isCharsetRule());
+    ASSERT(!rule->isCharsetRule());
     
     unsigned childVectorIndex = index;
-    // m_children does not contain @charset which is always in index 0 if it exists.
+    // m_childRules does not contain @charset which is always in index 0 if it exists.
     if (hasCharsetRule()) {
         if (index == 0) {
             // Nothing can be inserted before @charset.
@@ -206,26 +224,30 @@
         }
         --childVectorIndex;
     }
+    
+    if (childVectorIndex < m_importRules.size() || (childVectorIndex == m_importRules.size() && rule->isImportRule())) {
+        // Inserting non-import rule before @import is not allowed.
+        if (!rule->isImportRule()) {
+            ec = HIERARCHY_REQUEST_ERR;
+            return 0;
+        }
+        m_importRules.insert(childVectorIndex, static_cast<CSSImportRule*>(rule.get()));
+        m_importRules[childVectorIndex]->requestStyleSheet();
 
-    // Throw a HIERARCHY_REQUEST_ERR exception if the rule cannot be inserted at the specified index. The best
-    // example of this is an @import rule inserted after regular rules.
-    if (r->isImportRule()) {
-        // Check all the rules that come before this one to make sure they are only @import rules.
-        for (unsigned i = 0; i < childVectorIndex; ++i) {
-            if (!m_children.at(i)->isImportRule()) {
-                ec = HIERARCHY_REQUEST_ERR;
-                return 0;
-            }
-        }
-    } 
+        // FIXME: Stylesheet doesn't actually change meaningfully before the imported sheets are loaded.
+        styleSheetChanged();
+        return index;
+    }
+    // Inserting @import rule after a non-import rule is not allowed.
+    if (rule->isImportRule()) {
+        ec = HIERARCHY_REQUEST_ERR;
+        return 0;
+    }
+    childVectorIndex -= m_importRules.size();
  
-    CSSRule* c = r.get();
-    m_children.insert(childVectorIndex, r.release());
-    if (c->isImportRule())
-        static_cast<CSSImportRule*>(c)->requestStyleSheet();
+    m_childRules.insert(childVectorIndex, rule.release());
 
     styleSheetChanged();
-
     return index;
 }
 
@@ -270,9 +292,16 @@
         }
         --childVectorIndex;
     }
+    if (childVectorIndex < m_importRules.size()) {
+        m_importRules[childVectorIndex]->setParentStyleSheet(0);
+        m_importRules.remove(childVectorIndex);
+        styleSheetChanged();
+        return;
+    }
+    childVectorIndex -= m_importRules.size();
 
-    m_children.at(childVectorIndex)->setParentStyleSheet(0);
-    m_children.remove(childVectorIndex);
+    m_childRules[childVectorIndex]->setParentStyleSheet(0);
+    m_childRules.remove(childVectorIndex);
     styleSheetChanged();
 }
 
@@ -317,9 +346,8 @@
 
 bool CSSStyleSheet::isLoading()
 {
-    for (unsigned i = 0; i < m_children.size(); ++i) {
-        CSSRule* rule = m_children.at(i).get();
-        if (rule->isImportRule() && static_cast<CSSImportRule*>(rule)->isLoading())
+    for (unsigned i = 0; i < m_importRules.size(); ++i) {
+        if (m_importRules[i]->isLoading())
             return true;
     }
     return false;
@@ -421,14 +449,17 @@
 
     while (!styleSheetQueue.isEmpty()) {
         CSSStyleSheet* styleSheet = styleSheetQueue.takeFirst();
+        
+        for (unsigned i = 0; i < styleSheet->m_importRules.size(); ++i) {
+            CSSImportRule* importRule = styleSheet->m_importRules[i].get();
+            if (importRule->styleSheet())
+                styleSheetQueue.append(importRule->styleSheet());
+            importRule->addSubresourceStyleURLs(urls);
+        }
 
-        for (unsigned i = 0; i < styleSheet->m_children.size(); ++i) {
-            CSSRule* rule = styleSheet->m_children.at(i).get();
-            if (rule->isImportRule()) {
-                if (CSSStyleSheet* ruleStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet())
-                    styleSheetQueue.append(ruleStyleSheet);
-                static_cast<CSSImportRule*>(rule)->addSubresourceStyleURLs(urls);
-            } else if (rule->isFontFaceRule())
+        for (unsigned i = 0; i < styleSheet->m_childRules.size(); ++i) {
+            CSSRule* rule = styleSheet->m_childRules[i].get();
+            if (rule->isFontFaceRule())
                 static_cast<CSSFontFaceRule*>(rule)->addSubresourceStyleURLs(urls);
             else if (rule->isStyleRule() || rule->isPageRule())
                 static_cast<CSSStyleRule*>(rule)->styleRule()->addSubresourceStyleURLs(urls, this);

Modified: trunk/Source/WebCore/css/CSSStyleSheet.h (112381 => 112382)


--- trunk/Source/WebCore/css/CSSStyleSheet.h	2012-03-28 10:10:14 UTC (rev 112381)
+++ trunk/Source/WebCore/css/CSSStyleSheet.h	2012-03-28 10:41:18 UTC (rev 112382)
@@ -28,6 +28,7 @@
 struct CSSNamespace;
 class CSSParser;
 class CSSCharsetRule;
+class CSSImportRule;
 class CSSRule;
 class CSSRuleList;
 class CachedCSSStyleSheet;
@@ -119,8 +120,9 @@
     unsigned length() const;
     CSSRule* item(unsigned index);
 
-    // Does not contain @charset rule.
-    const Vector<RefPtr<CSSRule> >& ruleVector() const { return m_children; }
+    // Rules other than @charset and @import.
+    const Vector<RefPtr<CSSRule> >& childRules() const { return m_childRules; }
+    const Vector<RefPtr<CSSImportRule> >& importRules() const { return m_importRules; }
 
     virtual MediaList* media() const OVERRIDE;
 
@@ -142,7 +144,8 @@
 
     String m_encodingFromCharsetRule;
     RefPtr<CSSCharsetRule> m_charsetRuleCSSOMWrapper;
-    Vector<RefPtr<CSSRule> > m_children;
+    Vector<RefPtr<CSSImportRule> > m_importRules;
+    Vector<RefPtr<CSSRule> > m_childRules;
     OwnPtr<CSSNamespace> m_namespaces;
     String m_charset;
     RefPtr<MediaQuerySet> m_mediaQueries;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to