<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[177964] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/177964">177964</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2015-01-06 09:57:52 -0800 (Tue, 06 Jan 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Regression(<a href="http://trac.webkit.org/projects/webkit/changeset/176212">r176212</a>): Carousel on mbusa.com is choppy
https://bugs.webkit.org/show_bug.cgi?id=139543
&lt;rdar://problem/19209406&gt;

Reviewed by Antti Koivisto.

Source/WebCore:

A repeating DOM timer changing the style of an element that has
overflowing content that is visible would get throttled in the
case where the overflowing content has its own layer. This is
because the repaint rect returned by
RenderObject::absoluteClippedOverflowRect() does not take into
consideration descendants with their own self-painting layer when
accounting for the overflow.

Until I can find a relatively cheap way of computing the overflow
in this case, this patch takes the conservative approach and
assumes we may repaint inside the viewport if the element does not
have a layer or if any of its descendants has its own layer.

This patch also renames isInsideViewport() function to
mayCauseRepaintInsideViewport() for clarity.

Tests: fast/dom/repeating-timer-element-overflow-hidden-throttling.html
       fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling.html

* dom/Element.cpp:
(WebCore::Element::mayCauseRepaintInsideViewport):
(WebCore::Element::isInsideViewport): Deleted.
* dom/Element.h:
* page/DOMTimer.cpp:
(WebCore::DOMTimer::scriptDidCauseElementRepaint):
(WebCore::DOMTimer::updateThrottlingStateAfterViewportChange):
* rendering/RenderElement.cpp:
(WebCore::RenderElement::mayCauseRepaintInsideViewport):
(WebCore::RenderElement::isInsideViewport): Deleted.
* rendering/RenderElement.h:

LayoutTests:

Add a layout test to cover the case where a repeating DOM timer is
changing the style of an element which has overflowing content that
is visible and has its own layer. In such case, the DOM timer should
not be throttled. Also add a layout test to make sure we still throttle
if the element clips its overflow.

* fast/dom/repeating-timer-element-overflow-hidden-throttling-expected.txt: Added.
* fast/dom/repeating-timer-element-overflow-hidden-throttling.html: Added.
* fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling-expected.txt: Added.
* fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling.html: Added.
New tests.

* fast/dom/timer-unthrottle-on-layout-expected.txt:
* fast/dom/timer-unthrottle-on-layout.html:
* fast/dom/timer-unthrottle-on-scroll-expected.txt:
* fast/dom/timer-unthrottle-on-scroll.html:
Stop using &lt;input&gt; test elements as it appears one of the descendants
in its shadow tree has its own layer.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastdomtimerunthrottleonlayoutexpectedtxt">trunk/LayoutTests/fast/dom/timer-unthrottle-on-layout-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastdomtimerunthrottleonlayouthtml">trunk/LayoutTests/fast/dom/timer-unthrottle-on-layout.html</a></li>
<li><a href="#trunkLayoutTestsfastdomtimerunthrottleonscrollexpectedtxt">trunk/LayoutTests/fast/dom/timer-unthrottle-on-scroll-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastdomtimerunthrottleonscrollhtml">trunk/LayoutTests/fast/dom/timer-unthrottle-on-scroll.html</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoredomElementcpp">trunk/Source/WebCore/dom/Element.cpp</a></li>
<li><a href="#trunkSourceWebCoredomElementh">trunk/Source/WebCore/dom/Element.h</a></li>
<li><a href="#trunkSourceWebCorepageDOMTimercpp">trunk/Source/WebCore/page/DOMTimer.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderElementcpp">trunk/Source/WebCore/rendering/RenderElement.cpp</a></li>
<li><a href="#trunkSourceWebCorerenderingRenderElementh">trunk/Source/WebCore/rendering/RenderElement.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsfastdomrepeatingtimerelementoverflowhiddenthrottlingexpectedtxt">trunk/LayoutTests/fast/dom/repeating-timer-element-overflow-hidden-throttling-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastdomrepeatingtimerelementoverflowhiddenthrottlinghtml">trunk/LayoutTests/fast/dom/repeating-timer-element-overflow-hidden-throttling.html</a></li>
<li><a href="#trunkLayoutTestsfastdomrepeatingtimerelementoverflowingchildownlayerthrottlingexpectedtxt">trunk/LayoutTests/fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling-expected.txt</a></li>
<li><a href="#trunkLayoutTestsfastdomrepeatingtimerelementoverflowingchildownlayerthrottlinghtml">trunk/LayoutTests/fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/LayoutTests/ChangeLog        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2015-01-06  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        Regression(r176212): Carousel on mbusa.com is choppy
+        https://bugs.webkit.org/show_bug.cgi?id=139543
+        &lt;rdar://problem/19209406&gt;
+
+        Reviewed by Antti Koivisto.
+
+        Add a layout test to cover the case where a repeating DOM timer is
+        changing the style of an element which has overflowing content that
+        is visible and has its own layer. In such case, the DOM timer should
+        not be throttled. Also add a layout test to make sure we still throttle
+        if the element clips its overflow.
+
+        * fast/dom/repeating-timer-element-overflow-hidden-throttling-expected.txt: Added.
+        * fast/dom/repeating-timer-element-overflow-hidden-throttling.html: Added.
+        * fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling-expected.txt: Added.
+        * fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling.html: Added.
+        New tests.
+
+        * fast/dom/timer-unthrottle-on-layout-expected.txt:
+        * fast/dom/timer-unthrottle-on-layout.html:
+        * fast/dom/timer-unthrottle-on-scroll-expected.txt:
+        * fast/dom/timer-unthrottle-on-scroll.html:
+        Stop using &lt;input&gt; test elements as it appears one of the descendants
+        in its shadow tree has its own layer.
+
</ins><span class="cx"> 2015-01-06  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         fast/events/before-unload-adopt-subframe-to-outside.html is flaky with ASan
</span></span></pre></div>
<a id="trunkLayoutTestsfastdomrepeatingtimerelementoverflowhiddenthrottlingexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/dom/repeating-timer-element-overflow-hidden-throttling-expected.txt (0 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/repeating-timer-element-overflow-hidden-throttling-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/dom/repeating-timer-element-overflow-hidden-throttling-expected.txt        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+Tests that a repeating timer changing the style of an element with 0 height and hidden overflow content that have their own layer gets throttled.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS testElement.offsetHeight is 0
+The timer should initially not be throttled.
+PASS internals.isTimerThrottled(timeoutId) is false
+5th iteration, timer should have been throttled.
+PASS wasThrottled is true
+6th iteration, timer should still be unthrottled.
+PASS internals.isTimerThrottled(timeoutId) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomrepeatingtimerelementoverflowhiddenthrottlinghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/dom/repeating-timer-element-overflow-hidden-throttling.html (0 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/repeating-timer-element-overflow-hidden-throttling.html                                (rev 0)
+++ trunk/LayoutTests/fast/dom/repeating-timer-element-overflow-hidden-throttling.html        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;div id=&quot;testElement&quot; style=&quot;height: 0; overflow: hidden;&quot;&gt;
+&lt;div style=&quot;-webkit-transform: translateX(0);&quot;&gt;test1&lt;/div&gt;
+&lt;div style=&quot;-webkit-transform: translateX(0);&quot;&gt;test2&lt;/div&gt;
+&lt;/div&gt;
+&lt;script&gt;
+description(&quot;Tests that a repeating timer changing the style of an element with 0 height and hidden overflow content that have their own layer gets throttled.&quot;);
+jsTestIsAsync = true;
+
+var iterationCount = 0;
+var timeoutId;
+var testElement = document.getElementById(&quot;testElement&quot;);
+var wasThrottled = false;
+
+function timerCallback()
+{
+  ++iterationCount;
+  // Interact with the style of the element.
+  testElement.style[&quot;left&quot;] = &quot;&quot; + iterationCount + &quot;px&quot;;
+
+  // 5 iterations should suffice to throttle the timer.
+  if (iterationCount == 5) {
+    // Do not use shouldBeTrue() here because it would cause a DOM tree mutation and
+    // unthrottle the DOM Timer.
+    wasThrottled = internals.isTimerThrottled(timeoutId);
+  } else if (iterationCount == 6) {
+    debug(&quot;5th iteration, timer should have been throttled.&quot;);
+    shouldBeTrue(&quot;wasThrottled&quot;);
+    debug(&quot;6th iteration, timer should still be unthrottled.&quot;);
+    shouldBeTrue(&quot;internals.isTimerThrottled(timeoutId)&quot;);
+    clearInterval(timeoutId);
+    finishJSTest();
+  }
+}
+
+shouldBe(&quot;testElement.offsetHeight&quot;, &quot;0&quot;);
+
+timeoutId = setInterval(timerCallback, 0);
+debug(&quot;The timer should initially not be throttled.&quot;);
+shouldBeFalse(&quot;internals.isTimerThrottled(timeoutId)&quot;);
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomrepeatingtimerelementoverflowingchildownlayerthrottlingexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling-expected.txt (0 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling-expected.txt                                (rev 0)
+++ trunk/LayoutTests/fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling-expected.txt        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -0,0 +1,17 @@
</span><ins>+Tests that a repeating timer changing the style of an element with 0 height and visible overflowing content that have their own layer does not get throttled.
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS testElement.offsetHeight is 0
+The timer should initially not be throttled.
+PASS internals.isTimerThrottled(timeoutId) is false
+5th iteration, timer should not have been throttled.
+PASS wasThrottled is false
+6th iteration, timer should still be unthrottled.
+PASS internals.isTimerThrottled(timeoutId) is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+test1
+test2
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomrepeatingtimerelementoverflowingchildownlayerthrottlinghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling.html (0 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling.html                                (rev 0)
+++ trunk/LayoutTests/fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling.html        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;div id=&quot;testElement&quot; style=&quot;height: 0;&quot;&gt;
+&lt;div style=&quot;-webkit-transform: translateX(0);&quot;&gt;test1&lt;/div&gt;
+&lt;div style=&quot;-webkit-transform: translateX(0);&quot;&gt;test2&lt;/div&gt;
+&lt;/div&gt;
+&lt;script&gt;
+description(&quot;Tests that a repeating timer changing the style of an element with 0 height and visible overflowing content that have their own layer does not get throttled.&quot;);
+jsTestIsAsync = true;
+
+var iterationCount = 0;
+var timeoutId;
+var testElement = document.getElementById(&quot;testElement&quot;);
+var wasThrottled = false;
+
+function timerCallback()
+{
+  ++iterationCount;
+  // Interact with the style of the element.
+  testElement.style[&quot;left&quot;] = &quot;&quot; + iterationCount + &quot;px&quot;;
+
+  // 5 iterations should suffice to throttle the timer.
+  if (iterationCount == 5) {
+    // Do not use shouldBeFalse() here because it would cause a DOM tree mutation and
+    // unthrottle the DOM Timer.
+    wasThrottled = internals.isTimerThrottled(timeoutId);
+  } else if (iterationCount == 6) {
+    debug(&quot;5th iteration, timer should not have been throttled.&quot;);
+    shouldBeFalse(&quot;wasThrottled&quot;);
+    debug(&quot;6th iteration, timer should still be unthrottled.&quot;);
+    shouldBeFalse(&quot;internals.isTimerThrottled(timeoutId)&quot;);
+    clearInterval(timeoutId);
+    finishJSTest();
+  }
+}
+
+shouldBe(&quot;testElement.offsetHeight&quot;, &quot;0&quot;);
+
+timeoutId = setInterval(timerCallback, 0);
+debug(&quot;The timer should initially not be throttled.&quot;);
+shouldBeFalse(&quot;internals.isTimerThrottled(timeoutId)&quot;);
+&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomtimerunthrottleonlayoutexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/dom/timer-unthrottle-on-layout-expected.txt (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/timer-unthrottle-on-layout-expected.txt        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/LayoutTests/fast/dom/timer-unthrottle-on-layout-expected.txt        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -16,4 +16,4 @@
</span><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span><del>-
</del><ins>+TEST
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomtimerunthrottleonlayouthtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/dom/timer-unthrottle-on-layout.html (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/timer-unthrottle-on-layout.html        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/LayoutTests/fast/dom/timer-unthrottle-on-layout.html        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -2,13 +2,15 @@
</span><span class="cx"> &lt;body&gt;
</span><span class="cx"> &lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> &lt;div style=&quot;position: relative; width: 1600px; height: 2400px; background-color: green;&quot;&gt;
</span><del>-  &lt;div id=&quot;parentDiv&quot; style=&quot;position:absolute; left: 600px; top: 800px;&quot;&gt; &lt;input id=&quot;textbox&quot; type=&quot;text&quot;&gt;&lt;/div&gt;
</del><ins>+  &lt;div id=&quot;parentDiv&quot; style=&quot;position:absolute; left: 600px; top: 800px;&quot;&gt;
+    &lt;div id=&quot;testElement&quot;&gt;TEST&lt;/div&gt;
+  &lt;/div&gt;
</ins><span class="cx"> &lt;/div&gt;
</span><span class="cx"> &lt;script&gt;
</span><span class="cx"> description(&quot;Tests that a repeating timer changing the style of an element outside viewport gets unthrottled if the elements is inside the viewport after layout.&quot;);
</span><span class="cx"> jsTestIsAsync = true;
</span><span class="cx"> 
</span><del>-var testElement = document.getElementById('textbox');
</del><ins>+var testElement = document.getElementById('testElement');
</ins><span class="cx"> var iterationCount = 0;
</span><span class="cx"> var wasThrottled = false;
</span><span class="cx"> var wasThrottledBeforeScroll = false;
</span></span></pre></div>
<a id="trunkLayoutTestsfastdomtimerunthrottleonscrollexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/dom/timer-unthrottle-on-scroll-expected.txt (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/timer-unthrottle-on-scroll-expected.txt        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/LayoutTests/fast/dom/timer-unthrottle-on-scroll-expected.txt        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -16,4 +16,4 @@
</span><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span><del>-
</del><ins>+TEST
</ins></span></pre></div>
<a id="trunkLayoutTestsfastdomtimerunthrottleonscrollhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/dom/timer-unthrottle-on-scroll.html (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/timer-unthrottle-on-scroll.html        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/LayoutTests/fast/dom/timer-unthrottle-on-scroll.html        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -2,13 +2,15 @@
</span><span class="cx"> &lt;body&gt;
</span><span class="cx"> &lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
</span><span class="cx"> &lt;div style=&quot;position: relative; width: 1600px; height: 2400px; background-color: green;&quot;&gt;
</span><del>-  &lt;div style=&quot;position:absolute; left: 600px; top: 800px;&quot;&gt; &lt;input id=&quot;textbox&quot; type=&quot;text&quot;&gt;&lt;/div&gt;
</del><ins>+  &lt;div style=&quot;position:absolute; left: 600px; top: 800px;&quot;&gt;
+    &lt;div id=&quot;testElement&quot;&gt;TEST&lt;/div&gt;
+  &lt;/div&gt;
</ins><span class="cx"> &lt;/div&gt;
</span><span class="cx"> &lt;script&gt;
</span><span class="cx"> description(&quot;Tests that a repeating timer changing the style of an element outside viewport gets unthrottled when scrolling the element into view.&quot;);
</span><span class="cx"> jsTestIsAsync = true;
</span><span class="cx"> 
</span><del>-var testElement = document.getElementById('textbox');
</del><ins>+var testElement = document.getElementById('testElement');
</ins><span class="cx"> var iterationCount = 0;
</span><span class="cx"> var wasThrottled = false;
</span><span class="cx"> var wasThrottledBeforeScroll = false;
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/Source/WebCore/ChangeLog        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -1,3 +1,42 @@
</span><ins>+2015-01-06  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        Regression(r176212): Carousel on mbusa.com is choppy
+        https://bugs.webkit.org/show_bug.cgi?id=139543
+        &lt;rdar://problem/19209406&gt;
+
+        Reviewed by Antti Koivisto.
+
+        A repeating DOM timer changing the style of an element that has
+        overflowing content that is visible would get throttled in the
+        case where the overflowing content has its own layer. This is
+        because the repaint rect returned by
+        RenderObject::absoluteClippedOverflowRect() does not take into
+        consideration descendants with their own self-painting layer when
+        accounting for the overflow.
+
+        Until I can find a relatively cheap way of computing the overflow
+        in this case, this patch takes the conservative approach and
+        assumes we may repaint inside the viewport if the element does not
+        have a layer or if any of its descendants has its own layer.
+
+        This patch also renames isInsideViewport() function to
+        mayCauseRepaintInsideViewport() for clarity.
+
+        Tests: fast/dom/repeating-timer-element-overflow-hidden-throttling.html
+               fast/dom/repeating-timer-element-overflowing-child-own-layer-throttling.html
+
+        * dom/Element.cpp:
+        (WebCore::Element::mayCauseRepaintInsideViewport):
+        (WebCore::Element::isInsideViewport): Deleted.
+        * dom/Element.h:
+        * page/DOMTimer.cpp:
+        (WebCore::DOMTimer::scriptDidCauseElementRepaint):
+        (WebCore::DOMTimer::updateThrottlingStateAfterViewportChange):
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::mayCauseRepaintInsideViewport):
+        (WebCore::RenderElement::isInsideViewport): Deleted.
+        * rendering/RenderElement.h:
+
</ins><span class="cx"> 2015-01-06  Anders Carlsson  &lt;andersca@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add a WebKit1 database provider
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.cpp (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Element.cpp        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/Source/WebCore/dom/Element.cpp        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -2421,9 +2421,9 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool Element::isInsideViewport(const IntRect* visibleRect) const
</del><ins>+bool Element::mayCauseRepaintInsideViewport(const IntRect* visibleRect) const
</ins><span class="cx"> {
</span><del>-    return renderer() &amp;&amp; renderer()-&gt;isInsideViewport(visibleRect);
</del><ins>+    return renderer() &amp;&amp; renderer()-&gt;mayCauseRepaintInsideViewport(visibleRect);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> DOMTokenList&amp; Element::classList()
</span></span></pre></div>
<a id="trunkSourceWebCoredomElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/dom/Element.h (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/dom/Element.h        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/Source/WebCore/dom/Element.h        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -200,7 +200,7 @@
</span><span class="cx">     double offsetWidth();
</span><span class="cx">     double offsetHeight();
</span><span class="cx"> 
</span><del>-    bool isInsideViewport(const IntRect* visibleRect = nullptr) const;
</del><ins>+    bool mayCauseRepaintInsideViewport(const IntRect* visibleRect = nullptr) const;
</ins><span class="cx"> 
</span><span class="cx">     // FIXME: Replace uses of offsetParent in the platform with calls
</span><span class="cx">     // to the render layer and merge bindingsOffsetParent and offsetParent.
</span></span></pre></div>
<a id="trunkSourceWebCorepageDOMTimercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/DOMTimer.cpp (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/DOMTimer.cpp        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/Source/WebCore/page/DOMTimer.cpp        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -321,7 +321,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (element.isInsideViewport())
</del><ins>+    if (element.mayCauseRepaintInsideViewport())
</ins><span class="cx">         DOMTimerFireState::current-&gt;setScriptMadeUserObservableChanges();
</span><span class="cx">     else
</span><span class="cx">         DOMTimerFireState::current-&gt;setScriptMadeNonUserObservableChangesToElement(element);
</span><span class="lines">@@ -480,7 +480,7 @@
</span><span class="cx">         if (!element || !element-&gt;inDocument())
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><del>-        if (element-&gt;isInsideViewport(&amp;visibleRect)) {
</del><ins>+        if (element-&gt;mayCauseRepaintInsideViewport(&amp;visibleRect)) {
</ins><span class="cx">             LOG(DOMTimers, &quot;%p - Script is changing style of an element that is now inside the viewport, unthrottling the timer.&quot;, this);
</span><span class="cx">             m_throttleState = ShouldNotThrottle;
</span><span class="cx">             unregisterForViewportChanges();
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderElementcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderElement.cpp        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -1336,15 +1336,23 @@
</span><span class="cx">     return borderImage &amp;&amp; borderImage-&gt;canRender(this, style().effectiveZoom()) &amp;&amp; borderImage-&gt;isLoaded();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool RenderElement::isInsideViewport(const IntRect* visibleRect) const
</del><ins>+bool RenderElement::mayCauseRepaintInsideViewport(const IntRect* optionalViewportRect) const
</ins><span class="cx"> {
</span><span class="cx">     auto&amp; frameView = view().frameView();
</span><span class="cx">     if (frameView.isOffscreen())
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    if (!hasOverflowClip()) {
+        // FIXME: Computing the overflow rect is expensive if any descendant has
+        // its own self-painting layer. As a result, we prefer to abort early in
+        // this case and assume it may cause us to repaint inside the viewport.
+        if (!hasLayer() || downcast&lt;RenderLayerModelObject&gt;(*this).layer()-&gt;firstChild())
+            return true;
+    }
+
</ins><span class="cx">     // Compute viewport rect if it was not provided.
</span><del>-    const IntRect&amp; viewportRect = visibleRect ? *visibleRect : frameView.windowToContents(frameView.windowClipRect());
-    return viewportRect.intersects(enclosingIntRect(absoluteClippedOverflowRect()));
</del><ins>+    const IntRect&amp; visibleRect = optionalViewportRect ? *optionalViewportRect : frameView.windowToContents(frameView.windowClipRect());
+    return visibleRect.intersects(enclosingIntRect(absoluteClippedOverflowRect()));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static bool shouldRepaintForImageAnimation(const RenderElement&amp; renderer, const IntRect&amp; visibleRect)
</span></span></pre></div>
<a id="trunkSourceWebCorerenderingRenderElementh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/rendering/RenderElement.h (177963 => 177964)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/rendering/RenderElement.h        2015-01-06 17:53:29 UTC (rev 177963)
+++ trunk/Source/WebCore/rendering/RenderElement.h        2015-01-06 17:57:52 UTC (rev 177964)
</span><span class="lines">@@ -133,7 +133,7 @@
</span><span class="cx">     bool repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect&amp; oldBounds, const LayoutRect&amp; oldOutlineBox, const LayoutRect* newBoundsPtr = nullptr, const LayoutRect* newOutlineBoxPtr = nullptr);
</span><span class="cx"> 
</span><span class="cx">     bool borderImageIsLoadedAndCanBeRendered() const;
</span><del>-    bool isInsideViewport(const IntRect* visibleRect = nullptr) const;
</del><ins>+    bool mayCauseRepaintInsideViewport(const IntRect* visibleRect = nullptr) const;
</ins><span class="cx"> 
</span><span class="cx">     // Returns true if this renderer requires a new stacking context.
</span><span class="cx">     bool createsGroup() const { return isTransparent() || hasMask() || hasFilter() || hasBackdropFilter() || hasBlendMode(); }
</span></span></pre>
</div>
</div>

</body>
</html>