Title: [153347] trunk
Revision
153347
Author
[email protected]
Date
2013-07-25 14:40:55 -0700 (Thu, 25 Jul 2013)

Log Message

Don't force layout when querying a fixed or non-box margin/padding property
https://bugs.webkit.org/show_bug.cgi?id=118032

Reviewed by David Hyatt.

Source/WebCore: 

Merge https://chromium.googlesource.com/chromium/blink/+/66427d0825fcc2975bd50220cdcaa2504d6f36e5.

This patch avoids layout in ComputedStyleExtractor::propertyValue for margin and padding properties
when they are of fixed length. According to the Blink patch's author, this improves the page load
time of economist.com by 27%.

The actual code change is significantly different from the original Blink patch since we've done
some refactorins in r152938 and r153067 to make this change more self-contained.

Test: fast/css/computed-width-without-renderer.html

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::zoomAdjustedPaddingOrMarginPixelValue):
(WebCore::paddingOrMarginIsRendererDependent):
(WebCore::isLayoutDependent):
(WebCore::ComputedStyleExtractor::propertyValue):

LayoutTests: 

Add a regression test inspired by the one added in
https://chromium.googlesource.com/chromium/blink/+/ff234b1593b2b493d47f38f687d09a87bc42c9eb.

* fast/css/computed-width-without-renderer-expected.txt: Added.
* fast/css/computed-width-without-renderer.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (153346 => 153347)


--- trunk/LayoutTests/ChangeLog	2013-07-25 21:13:28 UTC (rev 153346)
+++ trunk/LayoutTests/ChangeLog	2013-07-25 21:40:55 UTC (rev 153347)
@@ -1,3 +1,16 @@
+2013-07-25  Ryosuke Niwa  <[email protected]>
+
+        Don't force layout when querying a fixed or non-box margin/padding property
+        https://bugs.webkit.org/show_bug.cgi?id=118032
+
+        Reviewed by David Hyatt.
+
+        Add a regression test inspired by the one added in
+        https://chromium.googlesource.com/chromium/blink/+/ff234b1593b2b493d47f38f687d09a87bc42c9eb.
+
+        * fast/css/computed-width-without-renderer-expected.txt: Added.
+        * fast/css/computed-width-without-renderer.html: Added.
+
 2013-07-25  Bear Travis  <[email protected]>
 
         [CSS Shapes] Fix typo in simple-polygon.js

Added: trunk/LayoutTests/fast/css/computed-width-without-renderer-expected.txt (0 => 153347)


--- trunk/LayoutTests/fast/css/computed-width-without-renderer-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/css/computed-width-without-renderer-expected.txt	2013-07-25 21:40:55 UTC (rev 153347)
@@ -0,0 +1,7 @@
+This tests obtaining widths of the same CSSComputedStyleDeclaration twice immediately after inserting a stylesheet. They should match.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS document.body.appendChild(div); style = getComputedStyle(div); style.width is style.width
+

Added: trunk/LayoutTests/fast/css/computed-width-without-renderer.html (0 => 153347)


--- trunk/LayoutTests/fast/css/computed-width-without-renderer.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/computed-width-without-renderer.html	2013-07-25 21:40:55 UTC (rev 153347)
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+if (window.testRunner)
+    testRunner.dumpAsText();
+
+var div;
+
+function runTest() {
+    description("This tests obtaining widths of the same CSSComputedStyleDeclaration twice immediately after inserting a stylesheet. They should match.");
+
+    var link = document.createElement('link');
+    link.rel = 'stylesheet';
+    link.href = ""
+    document.head.appendChild(link);
+
+    div = document.createElement('div');
+    shouldBe("document.body.appendChild(div); style = getComputedStyle(div); style.width", "style.width");
+}
+</script>
+</head>
+<body _onload_="runTest()">
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (153346 => 153347)


--- trunk/Source/WebCore/ChangeLog	2013-07-25 21:13:28 UTC (rev 153346)
+++ trunk/Source/WebCore/ChangeLog	2013-07-25 21:40:55 UTC (rev 153347)
@@ -1,3 +1,27 @@
+2013-07-25  Ryosuke Niwa  <[email protected]>
+
+        Don't force layout when querying a fixed or non-box margin/padding property
+        https://bugs.webkit.org/show_bug.cgi?id=118032
+
+        Reviewed by David Hyatt.
+
+        Merge https://chromium.googlesource.com/chromium/blink/+/66427d0825fcc2975bd50220cdcaa2504d6f36e5.
+
+        This patch avoids layout in ComputedStyleExtractor::propertyValue for margin and padding properties
+        when they are of fixed length. According to the Blink patch's author, this improves the page load
+        time of economist.com by 27%.
+
+        The actual code change is significantly different from the original Blink patch since we've done
+        some refactorins in r152938 and r153067 to make this change more self-contained.
+
+        Test: fast/css/computed-width-without-renderer.html
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::zoomAdjustedPaddingOrMarginPixelValue):
+        (WebCore::paddingOrMarginIsRendererDependent):
+        (WebCore::isLayoutDependent):
+        (WebCore::ComputedStyleExtractor::propertyValue):
+
 2013-07-25  Sam Weinig  <[email protected]>
 
         -[WebHTMLView attributedSubstringForProposedRange:actualRange:] does not include strikethrough attribute in the returned attributed string

Modified: trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp (153346 => 153347)


--- trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp	2013-07-25 21:13:28 UTC (rev 153346)
+++ trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp	2013-07-25 21:40:55 UTC (rev 153347)
@@ -1520,21 +1520,31 @@
     return cssValuePool().createIdentifierValue(CSSValueNormal);
 }
 
-static bool isLayoutDependentProperty(CSSPropertyID propertyID)
+typedef Length (RenderStyle::*RenderStyleLengthGetter)() const;
+typedef LayoutUnit (RenderBoxModelObject::*RenderBoxComputedCSSValueGetter)() const;
+
+template<RenderStyleLengthGetter lengthGetter, RenderBoxComputedCSSValueGetter computedCSSValueGetter>
+inline PassRefPtr<CSSValue> zoomAdjustedPaddingOrMarginPixelValue(RenderStyle* style, RenderObject* renderer)
 {
+    Length unzoomzedLength = (style->*lengthGetter)();
+    if (!renderer || !renderer->isBox() || unzoomzedLength.isFixed())
+        return zoomAdjustedPixelValueForLength(unzoomzedLength, style);
+    return zoomAdjustedPixelValue((toRenderBox(renderer)->*computedCSSValueGetter)(), style);
+}
+
+template<RenderStyleLengthGetter lengthGetter>
+inline bool paddingOrMarginIsRendererDependent(RenderStyle* style, RenderObject* renderer)
+{
+    if (!renderer || !renderer->isBox())
+        return false;
+    return !(style && (style->*lengthGetter)().isFixed());
+}
+
+static bool isLayoutDependent(CSSPropertyID propertyID, RenderStyle* style, RenderObject* renderer)
+{
     switch (propertyID) {
     case CSSPropertyWidth:
     case CSSPropertyHeight:
-    case CSSPropertyMargin:
-    case CSSPropertyMarginTop:
-    case CSSPropertyMarginBottom:
-    case CSSPropertyMarginLeft:
-    case CSSPropertyMarginRight:
-    case CSSPropertyPadding:
-    case CSSPropertyPaddingTop:
-    case CSSPropertyPaddingBottom:
-    case CSSPropertyPaddingLeft:
-    case CSSPropertyPaddingRight:
     case CSSPropertyWebkitPerspectiveOrigin:
     case CSSPropertyWebkitTransformOrigin:
     case CSSPropertyWebkitTransform:
@@ -1542,6 +1552,34 @@
     case CSSPropertyWebkitFilter:
 #endif
         return true;
+    case CSSPropertyMargin: {
+        if (!renderer || !renderer->isBox())
+            return false;
+        return !(style && style->marginTop().isFixed() && style->marginRight().isFixed()
+            && style->marginBottom().isFixed() && style->marginLeft().isFixed());
+    }
+    case CSSPropertyMarginTop:
+        return paddingOrMarginIsRendererDependent<&RenderStyle::marginTop>(style, renderer);
+    case CSSPropertyMarginRight:
+        return paddingOrMarginIsRendererDependent<&RenderStyle::marginRight>(style, renderer);
+    case CSSPropertyMarginBottom:
+        return paddingOrMarginIsRendererDependent<&RenderStyle::marginBottom>(style, renderer);
+    case CSSPropertyMarginLeft:
+        return paddingOrMarginIsRendererDependent<&RenderStyle::marginLeft>(style, renderer);
+    case CSSPropertyPadding: {
+        if (!renderer || !renderer->isBox())
+            return false;
+        return !(style && style->paddingTop().isFixed() && style->paddingRight().isFixed()
+            && style->paddingBottom().isFixed() && style->paddingLeft().isFixed());
+    }
+    case CSSPropertyPaddingTop:
+        return paddingOrMarginIsRendererDependent<&RenderStyle::paddingTop>(style, renderer);
+    case CSSPropertyPaddingRight:
+        return paddingOrMarginIsRendererDependent<&RenderStyle::paddingRight>(style, renderer);
+    case CSSPropertyPaddingBottom:
+        return paddingOrMarginIsRendererDependent<&RenderStyle::paddingBottom>(style, renderer);
+    case CSSPropertyPaddingLeft:
+        return paddingOrMarginIsRendererDependent<&RenderStyle::paddingLeft>(style, renderer); 
     default:
         return false;
     }
@@ -1596,47 +1634,48 @@
     return styledNode->computedStyle(styledNode->isPseudoElement() ? NOPSEUDO : pseudoElementSpecifier);
 }
 
-typedef Length (RenderStyle::*RenderStyleLengthGetter)() const;
-typedef LayoutUnit (RenderBoxModelObject::*RenderBoxComputedCSSValueGetter)() const;
-
-template<RenderStyleLengthGetter lengthGetter, RenderBoxComputedCSSValueGetter computedCSSValueGetter>
-inline PassRefPtr<CSSValue> zoomAdjustedPaddingOrMarginPixelValue(RenderStyle* style, RenderObject* renderer)
-{
-    Length unzoomedLength = (style->*lengthGetter)();
-    if (unzoomedLength.isFixed() || !renderer || !renderer->isBox())
-        return zoomAdjustedPixelValueForLength(unzoomedLength, style);
-    return zoomAdjustedPixelValue((toRenderBox(renderer)->*computedCSSValueGetter)(), style);
-}
-
 PassRefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID, EUpdateLayout updateLayout) const
 {
     Node* styledNode = this->styledNode();
     if (!styledNode)
         return 0;
 
+    RefPtr<RenderStyle> style;
+    RenderObject* renderer;
+    bool forceFullLayout = false;
     if (updateLayout) {
         Document* document = styledNode->document();
+
+        if (nodeOrItsAncestorNeedsStyleRecalc(styledNode)) {
+            document->updateStyleIfNeeded();
+            // The style recalc could have caused the styled node to be discarded or replaced
+            // if it was a PseudoElement so we need to update it.
+            styledNode = this->styledNode();
+        }
+
+        style = computeRenderStyleForProperty(styledNode, m_pseudoElementSpecifier, propertyID);
+        renderer = styledNode->renderer();
+
         // FIXME: Some of these cases could be narrowed down or optimized better.
-        bool forceFullLayout = isLayoutDependentProperty(propertyID)
+        forceFullLayout = isLayoutDependent(propertyID, style.get(), renderer)
             || styledNode->isInShadowTree()
             || (document->styleResolverIfExists() && document->styleResolverIfExists()->hasViewportDependentMediaQueries() && document->ownerElement())
             || document->seamlessParentIFrame();
 
-        if (forceFullLayout)
+        if (forceFullLayout) {
             document->updateLayoutIgnorePendingStylesheets();
-        else if (nodeOrItsAncestorNeedsStyleRecalc(styledNode))
-            document->updateStyleIfNeeded();
+            styledNode = this->styledNode();
+        }
+    }
 
-        // The style recalc could have caused the styled node to be discarded or replaced
-        // if it was a PseudoElement so we need to update it.
-        styledNode = this->styledNode();
+    if (!updateLayout || forceFullLayout) {
+        style = computeRenderStyleForProperty(styledNode, m_pseudoElementSpecifier, propertyID);
+        renderer = styledNode->renderer();
     }
 
-    RefPtr<RenderStyle> style = computeRenderStyleForProperty(styledNode, m_pseudoElementSpecifier, propertyID);
     if (!style)
         return 0;
 
-    RenderObject* renderer = styledNode->renderer();
     propertyID = CSSProperty::resolveDirectionAwareProperty(propertyID, style->direction(), style->writingMode());
 
     switch (propertyID) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to