Title: [153641] trunk/Source/WebCore
Revision
153641
Author
[email protected]
Date
2013-08-02 02:15:43 -0700 (Fri, 02 Aug 2013)

Log Message

Removing an empty style sheet shouldn't trigger style recalc.
<http://webkit.org/b/119248>
<rdar://problem/14629045>

Reviewed by Antti Koivisto.

Teach DocumentStyleSheetCollection to filter out empty style sheets when deciding whether
or not to trigger a style recalc. We can then be clever when an empty style sheet is removed
from the document, and avoid causing extra work.

Some pages use this pattern:

    (1) Create a <style> element.
    (2) Add it to the document's <head> element.
    (3) Insert some CSS as a text child of the <style> element.

Since the <style> element is already inside the document at (3), we had to treat this as an
old style sheet being removed, even though it was just an empty sheet of nothing.

With this patch, Document gains enough smarts to know that removing/adding an empty sheet
won't affect layout/rendering in any meaningful way, thus a style recalc can be avoided.

* dom/Document.h:
* dom/Document.cpp:
(WebCore::Document::styleResolverChanged):

    Add a DeferRecalcStyleIfNeeded mode to styleResolverChanged().

* css/CSSStyleSheet.h:
* css/CSSStyleSheet.cpp:
(WebCore::CSSStyleSheet::clearOwnerNode):

    Use DeferRecalcStyleIfNeeded when saying bye from a CSSStyleSheet and let Document decide
    if removing the sheet should trigger style recalc instead of always assuming it should.

* dom/DocumentStyleSheetCollection.cpp:
(WebCore::filterEnabledNonemptyCSSStyleSheets):
(WebCore::DocumentStyleSheetCollection::updateActiveStyleSheets):

    Exclude empty sheets from the activeAuthorStyleSheets() collection. They are still
    visible through CSSOM's document.styleSheets.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (153640 => 153641)


--- trunk/Source/WebCore/ChangeLog	2013-08-02 08:58:23 UTC (rev 153640)
+++ trunk/Source/WebCore/ChangeLog	2013-08-02 09:15:43 UTC (rev 153641)
@@ -1,3 +1,47 @@
+2013-08-01  Andreas Kling  <[email protected]>
+
+        Removing an empty style sheet shouldn't trigger style recalc.
+        <http://webkit.org/b/119248>
+        <rdar://problem/14629045>
+
+        Reviewed by Antti Koivisto.
+
+        Teach DocumentStyleSheetCollection to filter out empty style sheets when deciding whether
+        or not to trigger a style recalc. We can then be clever when an empty style sheet is removed
+        from the document, and avoid causing extra work.
+
+        Some pages use this pattern:
+
+            (1) Create a <style> element.
+            (2) Add it to the document's <head> element.
+            (3) Insert some CSS as a text child of the <style> element.
+
+        Since the <style> element is already inside the document at (3), we had to treat this as an
+        old style sheet being removed, even though it was just an empty sheet of nothing.
+
+        With this patch, Document gains enough smarts to know that removing/adding an empty sheet
+        won't affect layout/rendering in any meaningful way, thus a style recalc can be avoided.
+
+        * dom/Document.h:
+        * dom/Document.cpp:
+        (WebCore::Document::styleResolverChanged):
+
+            Add a DeferRecalcStyleIfNeeded mode to styleResolverChanged().
+
+        * css/CSSStyleSheet.h:
+        * css/CSSStyleSheet.cpp:
+        (WebCore::CSSStyleSheet::clearOwnerNode):
+
+            Use DeferRecalcStyleIfNeeded when saying bye from a CSSStyleSheet and let Document decide
+            if removing the sheet should trigger style recalc instead of always assuming it should.
+
+        * dom/DocumentStyleSheetCollection.cpp:
+        (WebCore::filterEnabledNonemptyCSSStyleSheets):
+        (WebCore::DocumentStyleSheetCollection::updateActiveStyleSheets):
+
+            Exclude empty sheets from the activeAuthorStyleSheets() collection. They are still
+            visible through CSSOM's document.styleSheets.
+
 2013-08-02  Zalan Bujtas  <[email protected]>
 
         Frame flattening: Change the logic on whether resize event needs to be dispatched.

Modified: trunk/Source/WebCore/css/CSSStyleSheet.cpp (153640 => 153641)


--- trunk/Source/WebCore/css/CSSStyleSheet.cpp	2013-08-02 08:58:23 UTC (rev 153640)
+++ trunk/Source/WebCore/css/CSSStyleSheet.cpp	2013-08-02 09:15:43 UTC (rev 153641)
@@ -163,6 +163,15 @@
     owner->styleResolverChanged(DeferRecalcStyle);
 }
 
+void CSSStyleSheet::clearOwnerNode()
+{
+    Document* owner = ownerDocument();
+    m_ownerNode = 0;
+    if (!owner)
+        return;
+    owner->styleResolverChanged(DeferRecalcStyleIfNeeded);
+}
+
 void CSSStyleSheet::reattachChildRuleCSSOMWrappers()
 {
     for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) {

Modified: trunk/Source/WebCore/css/CSSStyleSheet.h (153640 => 153641)


--- trunk/Source/WebCore/css/CSSStyleSheet.h	2013-08-02 08:58:23 UTC (rev 153640)
+++ trunk/Source/WebCore/css/CSSStyleSheet.h	2013-08-02 09:15:43 UTC (rev 153641)
@@ -74,7 +74,7 @@
     unsigned length() const;
     CSSRule* item(unsigned index);
 
-    virtual void clearOwnerNode() OVERRIDE { didMutate(); m_ownerNode = 0; }
+    virtual void clearOwnerNode() OVERRIDE;
     virtual CSSImportRule* ownerRule() const OVERRIDE { return m_ownerRule; }
     virtual KURL baseURL() const OVERRIDE;
     virtual bool isLoading() const OVERRIDE;

Modified: trunk/Source/WebCore/dom/Document.cpp (153640 => 153641)


--- trunk/Source/WebCore/dom/Document.cpp	2013-08-02 08:58:23 UTC (rev 153640)
+++ trunk/Source/WebCore/dom/Document.cpp	2013-08-02 09:15:43 UTC (rev 153641)
@@ -3155,7 +3155,7 @@
         printf("Beginning update of style selector at time %d.\n", elapsedTime());
 #endif
 
-    DocumentStyleSheetCollection::UpdateFlag styleSheetUpdate = (updateFlag == RecalcStyleIfNeeded)
+    DocumentStyleSheetCollection::UpdateFlag styleSheetUpdate = (updateFlag == RecalcStyleIfNeeded || updateFlag == DeferRecalcStyleIfNeeded)
         ? DocumentStyleSheetCollection::OptimizedUpdate
         : DocumentStyleSheetCollection::FullUpdate;
     bool stylesheetChangeRequiresStyleRecalc = m_styleSheetCollection->updateActiveStyleSheets(styleSheetUpdate);
@@ -3165,6 +3165,12 @@
         return;
     }
 
+    if (updateFlag == DeferRecalcStyleIfNeeded) {
+        if (stylesheetChangeRequiresStyleRecalc)
+            scheduleForcedStyleRecalc();
+        return;
+    }
+
     if (didLayoutWithPendingStylesheets() && !m_styleSheetCollection->hasPendingSheets()) {
         m_pendingSheetLayout = IgnoreLayoutWithPendingSheets;
         if (renderer())

Modified: trunk/Source/WebCore/dom/Document.h (153640 => 153641)


--- trunk/Source/WebCore/dom/Document.h	2013-08-02 08:58:23 UTC (rev 153640)
+++ trunk/Source/WebCore/dom/Document.h	2013-08-02 09:15:43 UTC (rev 153641)
@@ -197,7 +197,7 @@
     PageshowEventPersisted = 1
 };
 
-enum StyleResolverUpdateFlag { RecalcStyleImmediately, DeferRecalcStyle, RecalcStyleIfNeeded };
+enum StyleResolverUpdateFlag { RecalcStyleImmediately, DeferRecalcStyle, RecalcStyleIfNeeded, DeferRecalcStyleIfNeeded };
 
 enum NodeListInvalidationType {
     DoNotInvalidateOnAttributeChanges = 0,

Modified: trunk/Source/WebCore/dom/DocumentStyleSheetCollection.cpp (153640 => 153641)


--- trunk/Source/WebCore/dom/DocumentStyleSheetCollection.cpp	2013-08-02 08:58:23 UTC (rev 153640)
+++ trunk/Source/WebCore/dom/DocumentStyleSheetCollection.cpp	2013-08-02 09:15:43 UTC (rev 153641)
@@ -427,14 +427,17 @@
     return false;
 }
 
-static void filterEnabledCSSStyleSheets(Vector<RefPtr<CSSStyleSheet> >& result, const Vector<RefPtr<StyleSheet> >& sheets)
+static void filterEnabledNonemptyCSSStyleSheets(Vector<RefPtr<CSSStyleSheet> >& result, const Vector<RefPtr<StyleSheet> >& sheets)
 {
     for (unsigned i = 0; i < sheets.size(); ++i) {
         if (!sheets[i]->isCSSStyleSheet())
             continue;
         if (sheets[i]->disabled())
             continue;
-        result.append(static_cast<CSSStyleSheet*>(sheets[i].get()));
+        CSSStyleSheet* sheet = static_cast<CSSStyleSheet*>(sheets[i].get());
+        if (!sheet->length())
+            continue;
+        result.append(sheet);
     }
 }
 
@@ -467,7 +470,7 @@
     activeCSSStyleSheets.appendVector(injectedAuthorStyleSheets());
     activeCSSStyleSheets.appendVector(documentAuthorStyleSheets());
     collectActiveCSSStyleSheetsFromSeamlessParents(activeCSSStyleSheets, m_document);
-    filterEnabledCSSStyleSheets(activeCSSStyleSheets, activeStyleSheets);
+    filterEnabledNonemptyCSSStyleSheets(activeCSSStyleSheets, activeStyleSheets);
 
     StyleResolverUpdateType styleResolverUpdateType;
     bool requiresFullStyleRecalc;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to