Diff
Modified: trunk/LayoutTests/ChangeLog (176238 => 176239)
--- trunk/LayoutTests/ChangeLog 2014-11-18 01:13:16 UTC (rev 176238)
+++ trunk/LayoutTests/ChangeLog 2014-11-18 01:14:46 UTC (rev 176239)
@@ -1,3 +1,34 @@
+2014-11-17 Chris Dumez <[email protected]>
+
+ Add initial layout testing coverage for timer throttling
+ https://bugs.webkit.org/show_bug.cgi?id=138809
+
+ Reviewed by Simon Fraser.
+
+ Add initial layout test coverage for timer throttling. It currently
+ covers the following cases:
+ - Repeating timer changes the style of an Element that is visible
+ - Repeating timer changes the style of an Element that is not visible
+ (i.e. "display: none").
+ - Repeating timer doing DOM mutations
+ - Nested timer changes the style of an Element that is visible
+ - Nested timer changes the style of an Element that is not visible
+ (i.e. "display: none").
+ - Nested timer doing DOM mutations
+
+ More layout tests are coming. In particular, we should add coverage for
+ changing the style of an Element outside the viewport. We should also
+ Test that the timer gets unthrottled if necessary on scrolling / layout.
+
+ * fast/dom/nested-timer-invisible-element-throttling-expected.txt: Added.
+ * fast/dom/nested-timer-invisible-element-throttling.html: Added.
+ * fast/dom/nested-timer-visible-element-throttling-expected.txt: Added.
+ * fast/dom/nested-timer-visible-element-throttling.html: Added.
+ * fast/dom/repeating-timer-invisible-element-throttling-expected.txt: Added.
+ * fast/dom/repeating-timer-invisible-element-throttling.html: Added.
+ * fast/dom/repeating-timer-visible-element-throttling-expected.txt: Added.
+ * fast/dom/repeating-timer-visible-element-throttling.html: Added.
+
2014-11-17 Alexey Proskuryakov <[email protected]>
media/track/track-in-band-cues-added-once.html fails sometimes
Added: trunk/LayoutTests/fast/dom/nested-timer-invisible-element-throttling-expected.txt (0 => 176239)
--- trunk/LayoutTests/fast/dom/nested-timer-invisible-element-throttling-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/nested-timer-invisible-element-throttling-expected.txt 2014-11-18 01:14:46 UTC (rev 176239)
@@ -0,0 +1,18 @@
+Tests that a nested timer changing the style of a non-visible element gets throttled.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+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 throttled.
+PASS internals.isTimerThrottled(timeoutId) is true
+Timer mutated the DOM tree.
+7th iteration, timer should no longer be throttled.
+PASS internals.isTimerThrottled(timeoutId) is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/dom/nested-timer-invisible-element-throttling.html (0 => 176239)
--- trunk/LayoutTests/fast/dom/nested-timer-invisible-element-throttling.html (rev 0)
+++ trunk/LayoutTests/fast/dom/nested-timer-invisible-element-throttling.html 2014-11-18 01:14:46 UTC (rev 176239)
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<body>
+<script src=""
+<div id="testElement" style="display: none">Test</div>
+<script>
+description("Tests that a nested timer changing the style of a non-visible element gets throttled.");
+jsTestIsAsync = true;
+
+var iterationCount = 0;
+var timeoutId;
+var testElement = document.getElementById("testElement");
+var wasThrottled = false;
+
+function checkTimerThrottleState()
+{
+ 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("5th iteration, timer should have been throttled.");
+ shouldBeTrue("wasThrottled");
+ debug("6th iteration, timer should still be throttled.");
+ shouldBeTrue("internals.isTimerThrottled(timeoutId)");
+ } else if (iterationCount >= 6) {
+ // Timer should be unthrottled due to the DOM tree mutation caused by shouldBeTrue() in
+ // the previous iteration.
+ debug("" + iterationCount + "th iteration, timer should no longer be throttled.");
+ shouldBeFalse("internals.isTimerThrottled(timeoutId)");
+ clearTimeout(timeoutId);
+ finishJSTest();
+ }
+}
+
+function timerCallback()
+{
+ ++iterationCount;
+ // Interact with the style of the element.
+ testElement.style["left"] = "" + iterationCount + "px";
+
+ // 5 iterations should be sufficient to throttle the timer.
+ if (iterationCount >= 5) {
+ setTimeout(checkTimerThrottleState, 0);
+ if (iterationCount == 7) {
+ // The call to debug() mutates the DOM tree.
+ debug("Timer mutated the DOM tree.");
+ }
+ }
+
+ timeoutId = setTimeout(timerCallback, 0);
+}
+
+timeoutId = setTimeout(timerCallback, 0);
+debug("The timer should initially not be throttled.");
+shouldBeFalse("internals.isTimerThrottled(timeoutId)");
+</script>
+<script src=""
+</body>
Added: trunk/LayoutTests/fast/dom/nested-timer-visible-element-throttling-expected.txt (0 => 176239)
--- trunk/LayoutTests/fast/dom/nested-timer-visible-element-throttling-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/nested-timer-visible-element-throttling-expected.txt 2014-11-18 01:14:46 UTC (rev 176239)
@@ -0,0 +1,15 @@
+Tests that a nested timer changing the style of a visible element does not get throttled.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+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
+Test
Added: trunk/LayoutTests/fast/dom/nested-timer-visible-element-throttling.html (0 => 176239)
--- trunk/LayoutTests/fast/dom/nested-timer-visible-element-throttling.html (rev 0)
+++ trunk/LayoutTests/fast/dom/nested-timer-visible-element-throttling.html 2014-11-18 01:14:46 UTC (rev 176239)
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<body>
+<script src=""
+<div id="testElement">Test</div>
+<script>
+description("Tests that a nested timer changing the style of a visible element does not get throttled.");
+jsTestIsAsync = true;
+
+var iterationCount = 0;
+var timeoutId;
+var testElement = document.getElementById("testElement");
+var wasThrottled = false;
+
+function checkTimerThrottlingState() {
+ 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("5th iteration, timer should not have been throttled.");
+ shouldBeFalse("wasThrottled");
+ debug("6th iteration, timer should still be unthrottled.");
+ shouldBeFalse("internals.isTimerThrottled(timeoutId)");
+ clearTimeout(timeoutId);
+ finishJSTest();
+ }
+}
+
+function timerCallback()
+{
+ ++iterationCount;
+ // Interact with the style of the element.
+ testElement.style["left"] = "" + iterationCount + "px";
+
+ // 5 iterations should suffice to throttle the timer.
+ if (iterationCount >= 5)
+ setTimeout(checkTimerThrottlingState, 0);
+
+ timeoutId = setTimeout(timerCallback, 0);
+}
+
+timeoutId = setTimeout(timerCallback, 0);
+debug("The timer should initially not be throttled.");
+shouldBeFalse("internals.isTimerThrottled(timeoutId)");
+</script>
+<script src=""
+</body>
Added: trunk/LayoutTests/fast/dom/repeating-timer-invisible-element-throttling-expected.txt (0 => 176239)
--- trunk/LayoutTests/fast/dom/repeating-timer-invisible-element-throttling-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/repeating-timer-invisible-element-throttling-expected.txt 2014-11-18 01:14:46 UTC (rev 176239)
@@ -0,0 +1,18 @@
+Tests that a repeating timer changing the style of a non-visible element gets throttled.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+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 throttled.
+PASS internals.isTimerThrottled(timeoutId) is true
+Timer mutated the DOM tree.
+7th iteration, timer should no longer be throttled.
+PASS internals.isTimerThrottled(timeoutId) is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/fast/dom/repeating-timer-invisible-element-throttling.html (0 => 176239)
--- trunk/LayoutTests/fast/dom/repeating-timer-invisible-element-throttling.html (rev 0)
+++ trunk/LayoutTests/fast/dom/repeating-timer-invisible-element-throttling.html 2014-11-18 01:14:46 UTC (rev 176239)
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<body>
+<script src=""
+<div id="testElement" style="display: none">Test</div>
+<script>
+description("Tests that a repeating timer changing the style of a non-visible element gets throttled.");
+jsTestIsAsync = true;
+
+var iterationCount = 0;
+var timeoutId;
+var testElement = document.getElementById("testElement");
+var wasThrottled = false;
+
+function timerCallback()
+{
+ ++iterationCount;
+ // Interact with the style of the element.
+ testElement.style["left"] = "" + iterationCount + "px";
+
+ // 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("5th iteration, timer should have been throttled.");
+ shouldBeTrue("wasThrottled");
+ debug("6th iteration, timer should still be throttled.");
+ shouldBeTrue("internals.isTimerThrottled(timeoutId)");
+ debug("Timer mutated the DOM tree.");
+ } else if (iterationCount >= 6) {
+ // Timer should be unthrottled due to the DOM tree mutation caused by shouldBeTrue() in
+ // the previous iteration.
+ debug("" + iterationCount + "th iteration, timer should no longer be throttled.");
+ shouldBeFalse("internals.isTimerThrottled(timeoutId)");
+ clearInterval(timeoutId);
+ finishJSTest();
+ }
+}
+
+timeoutId = setInterval(timerCallback, 0);
+debug("The timer should initially not be throttled.");
+shouldBeFalse("internals.isTimerThrottled(timeoutId)");
+</script>
+<script src=""
+</body>
Added: trunk/LayoutTests/fast/dom/repeating-timer-visible-element-throttling-expected.txt (0 => 176239)
--- trunk/LayoutTests/fast/dom/repeating-timer-visible-element-throttling-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/dom/repeating-timer-visible-element-throttling-expected.txt 2014-11-18 01:14:46 UTC (rev 176239)
@@ -0,0 +1,15 @@
+Tests that a repeating timer changing the style of a visible element does not get throttled.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+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
+Test
Added: trunk/LayoutTests/fast/dom/repeating-timer-visible-element-throttling.html (0 => 176239)
--- trunk/LayoutTests/fast/dom/repeating-timer-visible-element-throttling.html (rev 0)
+++ trunk/LayoutTests/fast/dom/repeating-timer-visible-element-throttling.html 2014-11-18 01:14:46 UTC (rev 176239)
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<body>
+<script src=""
+<div id="testElement">Test</div>
+<script>
+description("Tests that a repeating timer changing the style of a visible element does not get throttled.");
+jsTestIsAsync = true;
+
+var iterationCount = 0;
+var timeoutId;
+var testElement = document.getElementById("testElement");
+var wasThrottled = false;
+
+function timerCallback()
+{
+ ++iterationCount;
+ // Interact with the style of the element.
+ testElement.style["left"] = "" + iterationCount + "px";
+
+ // 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("5th iteration, timer should not have been throttled.");
+ shouldBeFalse("wasThrottled");
+ debug("6th iteration, timer should still be unthrottled.");
+ shouldBeFalse("internals.isTimerThrottled(timeoutId)");
+ clearInterval(timeoutId);
+ finishJSTest();
+ }
+}
+
+timeoutId = setInterval(timerCallback, 0);
+debug("The timer should initially not be throttled.");
+shouldBeFalse("internals.isTimerThrottled(timeoutId)");
+</script>
+<script src=""
+</body>
Modified: trunk/Source/WebCore/ChangeLog (176238 => 176239)
--- trunk/Source/WebCore/ChangeLog 2014-11-18 01:13:16 UTC (rev 176238)
+++ trunk/Source/WebCore/ChangeLog 2014-11-18 01:14:46 UTC (rev 176239)
@@ -1,3 +1,24 @@
+2014-11-17 Chris Dumez <[email protected]>
+
+ Add initial layout testing coverage for timer throttling
+ https://bugs.webkit.org/show_bug.cgi?id=138809
+
+ Reviewed by Simon Fraser.
+
+ Add isTimerThrottled() API to Internals so that we can add layout test
+ coverage for timer throttling.
+
+ Tests: fast/dom/nested-timer-invisible-element-throttling.html
+ fast/dom/nested-timer-visible-element-throttling.html
+ fast/dom/repeating-timer-invisible-element-throttling.html
+ fast/dom/repeating-timer-visible-element-throttling.html
+
+ * page/DOMTimer.h:
+ * testing/Internals.cpp:
+ (WebCore::Internals::isTimerThrottled):
+ * testing/Internals.h:
+ * testing/Internals.idl:
+
2014-11-17 Zalan Bujtas <[email protected]>
Simple line layout: Rename FlowContentIterator and move implementation to SimpleLineLayoutFlowContents.cpp
Modified: trunk/Source/WebCore/page/DOMTimer.h (176238 => 176239)
--- trunk/Source/WebCore/page/DOMTimer.h 2014-11-18 01:13:16 UTC (rev 176238)
+++ trunk/Source/WebCore/page/DOMTimer.h 2014-11-18 01:14:46 UTC (rev 176239)
@@ -61,6 +61,8 @@
private:
DOMTimer(ScriptExecutionContext&, std::unique_ptr<ScheduledAction>, int interval, bool singleShot);
+ friend class Internals;
+
double intervalClampedToMinimum() const;
bool isIntervalDependentOnViewport() const { return m_throttleState == ShouldThrottle && !m_elementsCausingThrottling.isEmpty(); }
Modified: trunk/Source/WebCore/testing/Internals.cpp (176238 => 176239)
--- trunk/Source/WebCore/testing/Internals.cpp 2014-11-18 01:13:16 UTC (rev 176238)
+++ trunk/Source/WebCore/testing/Internals.cpp 2014-11-18 01:14:46 UTC (rev 176239)
@@ -626,6 +626,16 @@
return element->setPseudo(id);
}
+bool Internals::isTimerThrottled(int timeoutId, ExceptionCode& ec)
+{
+ DOMTimer* timer = scriptExecutionContext()->findTimeout(timeoutId);
+ if (!timer) {
+ ec = NOT_FOUND_ERR;
+ return false;
+ }
+ return timer->m_throttleState == DOMTimer::ShouldThrottle;
+}
+
String Internals::visiblePlaceholder(Element* element)
{
if (is<HTMLTextFormControlElement>(element)) {
Modified: trunk/Source/WebCore/testing/Internals.h (176238 => 176239)
--- trunk/Source/WebCore/testing/Internals.h 2014-11-18 01:13:16 UTC (rev 176238)
+++ trunk/Source/WebCore/testing/Internals.h 2014-11-18 01:14:46 UTC (rev 176239)
@@ -92,6 +92,9 @@
String shadowPseudoId(Element*, ExceptionCode&);
void setShadowPseudoId(Element*, const String&, ExceptionCode&);
+ // DOMTimers throttling testing.
+ bool isTimerThrottled(int timeoutId, ExceptionCode&);
+
// Spatial Navigation testing.
unsigned lastSpatialNavigationCandidateCount(ExceptionCode&) const;
Modified: trunk/Source/WebCore/testing/Internals.idl (176238 => 176239)
--- trunk/Source/WebCore/testing/Internals.idl 2014-11-18 01:13:16 UTC (rev 176238)
+++ trunk/Source/WebCore/testing/Internals.idl 2014-11-18 01:14:46 UTC (rev 176239)
@@ -238,6 +238,9 @@
[RaisesException] void startTrackingRepaints();
[RaisesException] void stopTrackingRepaints();
+ // Query if a timer is currently throttled, to debug timer throttling.
+ [RaisesException] boolean isTimerThrottled(long timerHandle);
+
// |node| should be Document, HTMLIFrameElement, or unspecified.
// If |node| is an HTMLIFrameElement, it assumes node.contentDocument is
// specified without security checks. Unspecified means this document.