[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.17-1283-gcf603cf
tkent at chromium.org
tkent at chromium.org
Tue Jan 5 23:44:18 UTC 2010
The following commit has been merged in the webkit-1.1 branch:
commit 89771bc9b9b4ae34a6d2ec1383c1c1f6016d49c2
Author: tkent at chromium.org <tkent at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date: Tue Dec 8 02:26:53 2009 +0000
2009-12-07 Kent Tamura <tkent at chromium.org>
Reviewed by Darin Adler.
Add tests for HTMLInputElement::stepUp() and stepDown().
https://bugs.webkit.org/show_bug.cgi?id=27451
* fast/forms/input-step-number-expected.txt: Added.
* fast/forms/input-step-number.html: Added.
* fast/forms/input-step-range-expected.txt: Added.
* fast/forms/input-step-range.html: Added.
* fast/forms/input-step-unsupported-expected.txt: Added.
* fast/forms/input-step-unsupported.html: Added.
* fast/forms/script-tests/input-step-number.js: Added.
* fast/forms/script-tests/input-step-range.js: Added.
* fast/forms/script-tests/input-step-unsupported.js: Added.
2009-12-07 Kent Tamura <tkent at chromium.org>
Reviewed by Darin Adler.
Add support for HTMLInputElement::stepUp() and stepDown() for
type=number and type=range.
https://bugs.webkit.org/show_bug.cgi?id=27451
Our implementation of stepUp() and stepDown() rounds the resultant
value to conform to the step value.
Change the number-string conversion method for RenderSlider to be
consistent with type=number.
Tests: fast/forms/input-step-number.html
fast/forms/input-step-range.html
fast/forms/input-step-unsupported.html
* html/HTMLInputElement.cpp:
(WebCore::HTMLInputElement::rangeUnderflow): Unify the code for NUMBER and RANGE.
(WebCore::HTMLInputElement::rangeOverflow): Unify the code for NUMBER and RANGE.
(WebCore::HTMLInputElement::minimum): Renamed from rangeMinimum(), and support for NUMBER.
(WebCore::HTMLInputElement::maximum): Renamed from rangeMaximum(), and support for NUMBER.
(WebCore::HTMLInputElement::stepBase):
(WebCore::HTMLInputElement::stepMismatch): Use stepBase().
(WebCore::HTMLInputElement::applyStepForNumberOrRange):
(WebCore::HTMLInputElement::stepUp):
(WebCore::HTMLInputElement::stepDown):
(WebCore::HTMLInputElement::formStringFromDouble):
* html/HTMLInputElement.h:
(WebCore::HTMLInputElement::stepUp):
(WebCore::HTMLInputElement::stepDown):
* html/HTMLInputElement.idl: Add stepUp() and stepDown().
* rendering/RenderSlider.cpp:
(WebCore::SliderRange::SliderRange): Sync with rangeMinimum()/rangeMaximum() renaming.
(WebCore::RenderSlider::updateFromElement): Use formStringFromDouble().
(WebCore::RenderSlider::setValueForPosition): Use formStringFromDouble().
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@51822 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 9f49b0e..ded83bb 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,20 @@
+2009-12-07 Kent Tamura <tkent at chromium.org>
+
+ Reviewed by Darin Adler.
+
+ Add tests for HTMLInputElement::stepUp() and stepDown().
+ https://bugs.webkit.org/show_bug.cgi?id=27451
+
+ * fast/forms/input-step-number-expected.txt: Added.
+ * fast/forms/input-step-number.html: Added.
+ * fast/forms/input-step-range-expected.txt: Added.
+ * fast/forms/input-step-range.html: Added.
+ * fast/forms/input-step-unsupported-expected.txt: Added.
+ * fast/forms/input-step-unsupported.html: Added.
+ * fast/forms/script-tests/input-step-number.js: Added.
+ * fast/forms/script-tests/input-step-range.js: Added.
+ * fast/forms/script-tests/input-step-unsupported.js: Added.
+
2009-12-07 Enrica Casucci <enrica at apple.com>
Reviewed by Darin Adler.
diff --git a/LayoutTests/fast/forms/input-step-number-expected.txt b/LayoutTests/fast/forms/input-step-number-expected.txt
new file mode 100644
index 0000000..ebee207
--- /dev/null
+++ b/LayoutTests/fast/forms/input-step-number-expected.txt
@@ -0,0 +1,89 @@
+Tests stepDown()/stepUp() for type=number.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Tests for an invalid current value:
+PASS input.stepDown() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.stepUp() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepDown("foo") with value=0:
+PASS input.value is "0"
+stepUp("foo") with value=0:
+PASS input.value is "0"
+stepDown(null) with value=0:
+PASS input.value is "0"
+stepUp(null) with value=0:
+PASS input.value is "0"
+stepDown(undefined) with value=0:
+PASS input.value is "0"
+stepUp(undefined) with value=0:
+PASS input.value is "0"
+stepUp() with value=0:
+PASS input.value is "1"
+stepUp(2) with value=1:
+PASS input.value is "3"
+stepUp(-1) with value=3:
+PASS input.value is "2"
+stepDown(-1) with value=2:
+PASS input.value is "1"
+stepDown(2) with value=1:
+PASS input.value is "-1"
+stepDown(-1) with value=-1:
+PASS input.value is "0"
+stepUp(1, 2) with value=0:
+PASS input.value is "1"
+stepUp(1, 3) with value=1:
+PASS input.value is "0"
+stepUp() with value=0 step=foo:
+PASS input.value is "1"
+stepUp() with value=1 step=0:
+PASS input.value is "2"
+stepUp() with value=2 step=-1:
+PASS input.value is "3"
+stepDown() and stepUp() with value=0 step=any:
+PASS input.stepDown() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.stepUp() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepDown() with value=1 min=0 step=1:
+PASS input.value is "0"
+stepDown() with value=0 min=0 step=1:
+PASS input.stepDown() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepDown(2) with value=1 min=0 step=1:
+PASS input.stepDown(2) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.value is "1"
+stepDown(2) with value=1 step=DBL_MAX:
+PASS input.stepDown(2) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepUp() with value=-1 max=0 step=1:
+PASS input.value is "0"
+stepUp() with value=0 max=0 step=1:
+PASS input.stepUp() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepUp(2) with value=-1 max=0 step=1:
+PASS input.stepUp(2) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.value is "-1"
+stepUp(2) with value=1 step=DBL_MAX:
+PASS input.stepUp(2) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepUp() with value=0 min=-1 step=2:
+PASS input.value is "3"
+PASS input.value is "1"
+stepUp(9) with value=9 min=0 step=10:
+PASS input.value is "100"
+stepDown() with value=19 min=0 step=10:
+PASS input.value is "10"
+stepUp() with value=89 min=0 max=99 step=10:
+PASS input.stepUp() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepUp(999999) with value=1e+308 step=1:
+PASS input.value is "1e+308"
+PASS input.value is "1e+308"
+stepUp(3) with value=0 step=0.33333333333333333:
+PASS input.value is "1"
+stepUp(10) with value=1 step=0.1:
+PASS input.value is "2"
+stepUp() x10 with value=2 step=0.1:
+PASS input.value is "3"
+stepUp(255) with value=0 min=0 max=1 step=0.003921568627450980:
+PASS input.value is "1"
+stepDown() x255 with value=1 min=0 max=1 step=0.003921568627450980:
+PASS input.value is "0"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/input-step-number.html b/LayoutTests/fast/forms/input-step-number.html
new file mode 100644
index 0000000..eb80ca6
--- /dev/null
+++ b/LayoutTests/fast/forms/input-step-number.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/input-step-number.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/forms/input-step-range-expected.txt b/LayoutTests/fast/forms/input-step-range-expected.txt
new file mode 100644
index 0000000..abff94c
--- /dev/null
+++ b/LayoutTests/fast/forms/input-step-range-expected.txt
@@ -0,0 +1,89 @@
+Tests stepDown()/stepUp() for type=range.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Tests for an invalid current value:
+PASS input.stepDown() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.stepUp() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepDown("foo") with value=0:
+PASS input.value is "0"
+stepUp("foo") with value=0:
+PASS input.value is "0"
+stepDown(null) with value=0:
+PASS input.value is "0"
+stepUp(null) with value=0:
+PASS input.value is "0"
+stepDown(undefined) with value=0:
+PASS input.value is "0"
+stepUp(undefined) with value=0:
+PASS input.value is "0"
+stepUp() with value=0 min=-100:
+PASS input.value is "1"
+stepUp(2) with value=1:
+PASS input.value is "3"
+stepUp(-1) with value=3:
+PASS input.value is "2"
+stepDown(-1) with value=2:
+PASS input.value is "1"
+stepDown(2) with value=1:
+PASS input.value is "-1"
+stepDown(-1) with value=-1:
+PASS input.value is "0"
+stepUp(1, 2) with value=0:
+PASS input.value is "1"
+stepUp(1, 3) with value=1:
+PASS input.value is "0"
+stepUp() with value=0 step=foo:
+PASS input.value is "1"
+stepUp() with value=1 step=0:
+PASS input.value is "2"
+stepUp() with value=2 step=-1:
+PASS input.value is "3"
+stepDown() and stepUp() with value=0 step=any:
+PASS input.stepDown() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.stepUp() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepDown() with value=1 min=0 step=1:
+PASS input.value is "0"
+stepDown() with value=0 min=0 step=1:
+PASS input.stepDown() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepDown(2) with value=1 min=0 step=1:
+PASS input.stepDown(2) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.value is "1"
+stepDown(2) with value=1 step=DBL_MAX:
+PASS input.stepDown(2) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepUp() with value=-1 min=-100 max=0 step=1:
+PASS input.value is "0"
+stepUp() with value=0 min=-100 max=0 step=1:
+PASS input.stepUp() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepUp(2) with value=-1 min=-100 max=0 step=1:
+PASS input.stepUp(2) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.value is "-1"
+stepUp(2) with value=1 step=DBL_MAX:
+PASS input.stepUp(2) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepUp() with value=0 min=-1 step=2:
+PASS input.value is "3"
+PASS input.value is "1"
+stepUp(9) with value=9 min=0 step=10:
+PASS input.value is "100"
+stepDown() with value=19 min=0 step=10:
+PASS input.value is "10"
+stepUp() with value=89 min=0 max=99 step=10:
+PASS input.stepUp() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+stepUp(999999) with value=1e+308 min=0 max=1.1e+308 step=1:
+PASS input.value is "1e+308"
+PASS input.value is "1e+308"
+stepUp(3) with value=0 step=0.33333333333333333:
+PASS input.value is "1"
+stepUp(10) with value=1 step=0.1:
+PASS input.value is "2"
+stepUp() x10 with value=2 step=0.1:
+PASS input.value is "3"
+stepUp(255) with value=0 min=0 max=1 step=0.003921568627450980:
+PASS input.value is "1"
+stepDown() x255 with value=1 min=0 max=1 step=0.003921568627450980:
+PASS input.value is "0"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/input-step-range.html b/LayoutTests/fast/forms/input-step-range.html
new file mode 100644
index 0000000..776b374
--- /dev/null
+++ b/LayoutTests/fast/forms/input-step-range.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/input-step-range.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/forms/input-step-unsupported-expected.txt b/LayoutTests/fast/forms/input-step-unsupported-expected.txt
new file mode 100644
index 0000000..df4a6ea
--- /dev/null
+++ b/LayoutTests/fast/forms/input-step-unsupported-expected.txt
@@ -0,0 +1,13 @@
+Tests stepDown()/stepUp() for unsupported types
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS input.stepDown() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.stepDown(0) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.stepUp() threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS input.stepUp(0) threw exception Error: INVALID_STATE_ERR: DOM Exception 11.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/forms/input-step-unsupported.html b/LayoutTests/fast/forms/input-step-unsupported.html
new file mode 100644
index 0000000..663caad
--- /dev/null
+++ b/LayoutTests/fast/forms/input-step-unsupported.html
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../../fast/js/resources/js-test-style.css">
+<script src="../../fast/js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/input-step-unsupported.js"></script>
+<script src="../../fast/js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/forms/script-tests/input-step-number.js b/LayoutTests/fast/forms/script-tests/input-step-number.js
new file mode 100644
index 0000000..80b489f
--- /dev/null
+++ b/LayoutTests/fast/forms/script-tests/input-step-number.js
@@ -0,0 +1,212 @@
+description('Tests stepDown()/stepUp() for type=number.');
+
+var input = document.createElement('input');
+input.type = 'number';
+var invalidStateErr = '"Error: INVALID_STATE_ERR: DOM Exception 11"';
+
+debug('Tests for an invalid current value:');
+input.value = '';
+shouldThrow('input.stepDown()', invalidStateErr);
+shouldThrow('input.stepUp()', invalidStateErr);
+
+// Non-number argument
+debug('stepDown("foo") with value=0:');
+input.value = '0';
+input.stepDown("foo");
+shouldBe('input.value', '"0"');
+
+debug('stepUp("foo") with value=0:');
+input.stepUp("foo");
+shouldBe('input.value', '"0"');
+
+debug('stepDown(null) with value=0:');
+input.stepDown(null);
+shouldBe('input.value', '"0"');
+
+debug('stepUp(null) with value=0:');
+input.stepUp(null);
+shouldBe('input.value', '"0"');
+
+debug('stepDown(undefined) with value=0:');
+input.stepDown(undefined);
+shouldBe('input.value', '"0"');
+
+debug('stepUp(undefined) with value=0:');
+input.stepUp(undefined);
+shouldBe('input.value', '"0"');
+
+// Default step value for type=number is 1.
+debug('stepUp() with value=0:');
+input.value = '0';
+input.stepUp();
+shouldBe('input.value', '"1"');
+
+debug('stepUp(2) with value=1:');
+input.stepUp(2);
+shouldBe('input.value', '"3"');
+
+debug('stepUp(-1) with value=3:');
+input.stepUp(-1);
+shouldBe('input.value', '"2"');
+
+debug('stepDown(-1) with value=2:');
+input.stepDown();
+shouldBe('input.value', '"1"');
+
+debug('stepDown(2) with value=1:');
+input.stepDown(2);
+shouldBe('input.value', '"-1"');
+
+debug('stepDown(-1) with value=-1:');
+input.stepDown(-1);
+shouldBe('input.value', '"0"');
+
+// Extra arguments are ignored.
+debug('stepUp(1, 2) with value=0:');
+input.stepUp(1, 2);
+shouldBe('input.value', '"1"');
+
+debug('stepUp(1, 3) with value=1:');
+input.stepDown(1, 3);
+shouldBe('input.value', '"0"');
+
+// The default value is used for invalid step values.
+debug('stepUp() with value=0 step=foo:');
+input.value = '0';
+input.step = 'foo';
+input.stepUp();
+shouldBe('input.value', '"1"');
+
+debug('stepUp() with value=1 step=0:');
+input.step = '0';
+input.stepUp();
+shouldBe('input.value', '"2"');
+
+debug('stepUp() with value=2 step=-1:');
+input.step = '-1';
+input.stepUp();
+shouldBe('input.value', '"3"');
+
+// No step value
+debug('stepDown() and stepUp() with value=0 step=any:');
+input.value = '0';
+input.step = 'any';
+shouldThrow('input.stepDown()', invalidStateErr);
+shouldThrow('input.stepUp()', invalidStateErr);
+
+// Minimum limit
+debug('stepDown() with value=1 min=0 step=1:');
+input.min = '0';
+input.step = '1';
+input.value = '1';
+input.stepDown();
+shouldBe('input.value', '"0"');
+debug('stepDown() with value=0 min=0 step=1:');
+shouldThrow('input.stepDown()', invalidStateErr);
+
+debug('stepDown(2) with value=1 min=0 step=1:');
+input.value = '1';
+shouldThrow('input.stepDown(2)', invalidStateErr);
+shouldBe('input.value', '"1"');
+
+// Should not be -Infinity.
+debug('stepDown(2) with value=1 step=DBL_MAX:');
+input.value = '1';
+input.min = '';
+input.step = '1.7976931348623156e+308';
+shouldThrow('input.stepDown(2)', invalidStateErr);
+
+// Maximum limit
+debug('stepUp() with value=-1 max=0 step=1:');
+input.value = '-1';
+input.min = '';
+input.max = '0';
+input.step = '1';
+input.stepUp();
+shouldBe('input.value', '"0"');
+debug('stepUp() with value=0 max=0 step=1:');
+shouldThrow('input.stepUp()', invalidStateErr);
+
+debug('stepUp(2) with value=-1 max=0 step=1:');
+input.value = '-1';
+shouldThrow('input.stepUp(2)', invalidStateErr);
+shouldBe('input.value', '"-1"');
+
+// Should not be Infinity.
+debug('stepUp(2) with value=1 step=DBL_MAX:');
+input.value = '1';
+input.max = '';
+input.step = '1.7976931348623156e+308';
+shouldThrow('input.stepUp(2)', invalidStateErr);
+
+// stepDown()/stepUp() for stepMismatch values
+debug('stepUp() with value=0 min=-1 step=2:');
+input.value = '0';
+input.min = '-1';
+input.step = '2';
+input.stepUp();
+shouldBe('input.value', '"3"');
+input.stepDown();
+shouldBe('input.value', '"1"');
+
+debug('stepUp(9) with value=9 min=0 step=10:');
+input.value = '9';
+input.min = '0';
+input.max = '';
+input.step = '10';
+input.stepUp(9);
+shouldBe('input.value', '"100"');
+
+debug('stepDown() with value=19 min=0 step=10:');
+input.value = '19';
+input.stepDown();
+shouldBe('input.value', '"10"');
+
+// value + step is <= max, but rounded result would be > max.
+debug('stepUp() with value=89 min=0 max=99 step=10:');
+input.value = '89';
+input.max = '99';
+shouldThrow('input.stepUp()', invalidStateErr);
+
+// Huge value and small step
+debug('stepUp(999999) with value=1e+308 step=1:');
+input.value = '1e+308';
+input.min = '';
+input.max = '';
+input.step = '1';
+input.stepUp(999999);
+shouldBe('input.value', '"1e+308"');
+input.stepDown(999999);
+shouldBe('input.value', '"1e+308"');
+
+// Fractional numbers
+debug('stepUp(3) with value=0 step=0.33333333333333333:');
+input.value = '0';
+input.min = '';
+input.max = '';
+input.step = '0.33333333333333333';
+input.stepUp(3);
+shouldBe('input.value', '"1"');
+
+debug('stepUp(10) with value=1 step=0.1:');
+input.step = '0.1';
+input.stepUp(10);
+shouldBe('input.value', '"2"');
+debug('stepUp() x10 with value=2 step=0.1:');
+for (var i = 0; i < 10; i++)
+ input.stepUp();
+shouldBe('input.value', '"3"');
+
+debug('stepUp(255) with value=0 min=0 max=1 step=0.003921568627450980:');
+input.value = '0';
+input.min = '0';
+input.max = '1';
+input.step = '0.003921568627450980';
+input.stepUp(255);
+shouldBe('input.value', '"1"');
+debug('stepDown() x255 with value=1 min=0 max=1 step=0.003921568627450980:');
+for (var i = 0; i < 255; i++)
+ input.stepDown();
+shouldBe('input.value', '"0"');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/fast/forms/script-tests/input-step-range.js b/LayoutTests/fast/forms/script-tests/input-step-range.js
new file mode 100644
index 0000000..d8745c1
--- /dev/null
+++ b/LayoutTests/fast/forms/script-tests/input-step-range.js
@@ -0,0 +1,213 @@
+description('Tests stepDown()/stepUp() for type=range.');
+
+var input = document.createElement('input');
+input.type = 'range';
+var invalidStateErr = '"Error: INVALID_STATE_ERR: DOM Exception 11"';
+
+debug('Tests for an invalid current value:');
+input.value = '';
+shouldThrow('input.stepDown()', invalidStateErr);
+shouldThrow('input.stepUp()', invalidStateErr);
+
+// Non-number argument
+debug('stepDown("foo") with value=0:');
+input.value = '0';
+input.stepDown("foo");
+shouldBe('input.value', '"0"');
+
+debug('stepUp("foo") with value=0:');
+input.stepUp("foo");
+shouldBe('input.value', '"0"');
+
+debug('stepDown(null) with value=0:');
+input.stepDown(null);
+shouldBe('input.value', '"0"');
+
+debug('stepUp(null) with value=0:');
+input.stepUp(null);
+shouldBe('input.value', '"0"');
+
+debug('stepDown(undefined) with value=0:');
+input.stepDown(undefined);
+shouldBe('input.value', '"0"');
+
+debug('stepUp(undefined) with value=0:');
+input.stepUp(undefined);
+shouldBe('input.value', '"0"');
+
+// Default step value for type=range is 1.
+debug('stepUp() with value=0 min=-100:');
+input.value = '0';
+input.min = '-100';
+input.stepUp();
+shouldBe('input.value', '"1"');
+
+debug('stepUp(2) with value=1:');
+input.stepUp(2);
+shouldBe('input.value', '"3"');
+
+debug('stepUp(-1) with value=3:');
+input.stepUp(-1);
+shouldBe('input.value', '"2"');
+
+debug('stepDown(-1) with value=2:');
+input.stepDown();
+shouldBe('input.value', '"1"');
+
+debug('stepDown(2) with value=1:');
+input.stepDown(2);
+shouldBe('input.value', '"-1"');
+
+debug('stepDown(-1) with value=-1:');
+input.stepDown(-1);
+shouldBe('input.value', '"0"');
+
+// Extra arguments are ignored.
+debug('stepUp(1, 2) with value=0:');
+input.stepUp(1, 2);
+shouldBe('input.value', '"1"');
+
+debug('stepUp(1, 3) with value=1:');
+input.stepDown(1, 3);
+shouldBe('input.value', '"0"');
+
+// The default value is used for invalid step values.
+debug('stepUp() with value=0 step=foo:');
+input.value = '0';
+input.step = 'foo';
+input.stepUp();
+shouldBe('input.value', '"1"');
+
+debug('stepUp() with value=1 step=0:');
+input.step = '0';
+input.stepUp();
+shouldBe('input.value', '"2"');
+
+debug('stepUp() with value=2 step=-1:');
+input.step = '-1';
+input.stepUp();
+shouldBe('input.value', '"3"');
+
+// No step value
+debug('stepDown() and stepUp() with value=0 step=any:');
+input.value = '0';
+input.step = 'any';
+shouldThrow('input.stepDown()', invalidStateErr);
+shouldThrow('input.stepUp()', invalidStateErr);
+
+// Minimum limit
+debug('stepDown() with value=1 min=0 step=1:');
+input.min = '0';
+input.step = '1';
+input.value = '1';
+input.stepDown();
+shouldBe('input.value', '"0"');
+debug('stepDown() with value=0 min=0 step=1:');
+shouldThrow('input.stepDown()', invalidStateErr);
+
+debug('stepDown(2) with value=1 min=0 step=1:');
+input.value = '1';
+shouldThrow('input.stepDown(2)', invalidStateErr);
+shouldBe('input.value', '"1"');
+
+// Implicit minimum.
+debug('stepDown(2) with value=1 step=DBL_MAX:');
+input.value = '1';
+input.min = '';
+input.step = '1.7976931348623156e+308';
+shouldThrow('input.stepDown(2)', invalidStateErr);
+
+// Maximum limit
+debug('stepUp() with value=-1 min=-100 max=0 step=1:');
+input.value = '-1';
+input.min = '-100';
+input.max = '0';
+input.step = '1';
+input.stepUp();
+shouldBe('input.value', '"0"');
+debug('stepUp() with value=0 min=-100 max=0 step=1:');
+shouldThrow('input.stepUp()', invalidStateErr);
+
+debug('stepUp(2) with value=-1 min=-100 max=0 step=1:');
+input.value = '-1';
+shouldThrow('input.stepUp(2)', invalidStateErr);
+shouldBe('input.value', '"-1"');
+
+// Implicit maximum
+debug('stepUp(2) with value=1 step=DBL_MAX:');
+input.value = '1';
+input.max = '';
+input.step = '1.7976931348623156e+308';
+shouldThrow('input.stepUp(2)', invalidStateErr);
+
+// stepDown()/stepUp() for stepMismatch values
+debug('stepUp() with value=0 min=-1 step=2:');
+input.value = '0';
+input.min = '-1';
+input.step = '2';
+input.stepUp();
+shouldBe('input.value', '"3"');
+input.stepDown();
+shouldBe('input.value', '"1"');
+
+debug('stepUp(9) with value=9 min=0 step=10:');
+input.value = '9';
+input.min = '0';
+input.max = '';
+input.step = '10';
+input.stepUp(9);
+shouldBe('input.value', '"100"');
+
+debug('stepDown() with value=19 min=0 step=10:');
+input.value = '19';
+input.stepDown();
+shouldBe('input.value', '"10"');
+
+// value + step is <= max, but rounded result would be > max.
+debug('stepUp() with value=89 min=0 max=99 step=10:');
+input.value = '89';
+input.max = '99';
+shouldThrow('input.stepUp()', invalidStateErr);
+
+// Huge value and small step
+debug('stepUp(999999) with value=1e+308 min=0 max=1.1e+308 step=1:');
+input.value = '1e+308';
+input.min = '0';
+input.max = '1.1e+308';
+input.step = '1';
+input.stepUp(999999);
+shouldBe('input.value', '"1e+308"');
+input.stepDown(999999);
+shouldBe('input.value', '"1e+308"');
+
+// Fractional numbers
+debug('stepUp(3) with value=0 step=0.33333333333333333:');
+input.value = '0';
+input.min = '';
+input.max = '';
+input.step = '0.33333333333333333';
+input.stepUp(3);
+shouldBe('input.value', '"1"');
+
+debug('stepUp(10) with value=1 step=0.1:');
+input.step = '0.1';
+input.stepUp(10);
+shouldBe('input.value', '"2"');
+debug('stepUp() x10 with value=2 step=0.1:');
+for (var i = 0; i < 10; i++)
+ input.stepUp();
+shouldBe('input.value', '"3"');
+
+debug('stepUp(255) with value=0 min=0 max=1 step=0.003921568627450980:');
+input.value = '0';
+input.min = '0';
+input.max = '1';
+input.step = '0.003921568627450980';
+input.stepUp(255);
+shouldBe('input.value', '"1"');
+debug('stepDown() x255 with value=1 min=0 max=1 step=0.003921568627450980:');
+for (var i = 0; i < 255; i++)
+ input.stepDown();
+shouldBe('input.value', '"0"');
+
+var successfullyParsed = true;
diff --git a/LayoutTests/fast/forms/script-tests/input-step-unsupported.js b/LayoutTests/fast/forms/script-tests/input-step-unsupported.js
new file mode 100644
index 0000000..9ccaf19
--- /dev/null
+++ b/LayoutTests/fast/forms/script-tests/input-step-unsupported.js
@@ -0,0 +1,12 @@
+description('Tests stepDown()/stepUp() for unsupported types');
+
+var input = document.createElement('input');
+input.type = 'text';
+input.step = '3';
+input.value = '2';
+shouldThrow('input.stepDown()', '"Error: INVALID_STATE_ERR: DOM Exception 11"');
+shouldThrow('input.stepDown(0)', '"Error: INVALID_STATE_ERR: DOM Exception 11"');
+shouldThrow('input.stepUp()', '"Error: INVALID_STATE_ERR: DOM Exception 11"');
+shouldThrow('input.stepUp(0)', '"Error: INVALID_STATE_ERR: DOM Exception 11"');
+
+var successfullyParsed = true;
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 6261e9d..4e6a570 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,40 @@
+2009-12-07 Kent Tamura <tkent at chromium.org>
+
+ Reviewed by Darin Adler.
+
+ Add support for HTMLInputElement::stepUp() and stepDown() for
+ type=number and type=range.
+ https://bugs.webkit.org/show_bug.cgi?id=27451
+
+ Our implementation of stepUp() and stepDown() rounds the resultant
+ value to conform to the step value.
+ Change the number-string conversion method for RenderSlider to be
+ consistent with type=number.
+
+ Tests: fast/forms/input-step-number.html
+ fast/forms/input-step-range.html
+ fast/forms/input-step-unsupported.html
+
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::rangeUnderflow): Unify the code for NUMBER and RANGE.
+ (WebCore::HTMLInputElement::rangeOverflow): Unify the code for NUMBER and RANGE.
+ (WebCore::HTMLInputElement::minimum): Renamed from rangeMinimum(), and support for NUMBER.
+ (WebCore::HTMLInputElement::maximum): Renamed from rangeMaximum(), and support for NUMBER.
+ (WebCore::HTMLInputElement::stepBase):
+ (WebCore::HTMLInputElement::stepMismatch): Use stepBase().
+ (WebCore::HTMLInputElement::applyStepForNumberOrRange):
+ (WebCore::HTMLInputElement::stepUp):
+ (WebCore::HTMLInputElement::stepDown):
+ (WebCore::HTMLInputElement::formStringFromDouble):
+ * html/HTMLInputElement.h:
+ (WebCore::HTMLInputElement::stepUp):
+ (WebCore::HTMLInputElement::stepDown):
+ * html/HTMLInputElement.idl: Add stepUp() and stepDown().
+ * rendering/RenderSlider.cpp:
+ (WebCore::SliderRange::SliderRange): Sync with rangeMinimum()/rangeMaximum() renaming.
+ (WebCore::RenderSlider::updateFromElement): Use formStringFromDouble().
+ (WebCore::RenderSlider::setValueForPosition): Use formStringFromDouble().
+
2009-12-07 Albert J. Wong <ajwong at chromium.org>
Not reviewed: Chromium build fix try 2 (dumb error).
diff --git a/WebCore/html/HTMLInputElement.cpp b/WebCore/html/HTMLInputElement.cpp
index 1578c6e..13dbbb0 100644
--- a/WebCore/html/HTMLInputElement.cpp
+++ b/WebCore/html/HTMLInputElement.cpp
@@ -65,6 +65,7 @@
#include <wtf/HashMap.h>
#include <wtf/MathExtras.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/dtoa.h>
using namespace std;
@@ -77,6 +78,12 @@ const int maxSavedResults = 256;
// Constant values for getAllowedValueStep().
static const double numberDefaultStep = 1.0;
static const double numberStepScaleFactor = 1.0;
+// Constant values for minimum().
+static const double numberDefaultMinimum = -DBL_MAX;
+static const double rangeDefaultMinimum = 0.0;
+// Constant values for maximum().
+static const double numberDefaultMaximum = DBL_MAX;
+static const double rangeDefaultMaximum = 100.0;
HTMLInputElement::HTMLInputElement(const QualifiedName& tagName, Document* doc, HTMLFormElement* f)
: HTMLTextFormControlElement(tagName, doc, f)
@@ -259,60 +266,62 @@ bool HTMLInputElement::tooLong() const
bool HTMLInputElement::rangeUnderflow() const
{
- if (inputType() == NUMBER) {
- double min = 0.0;
- double doubleValue = 0.0;
- if (formStringToDouble(getAttribute(minAttr), &min) && formStringToDouble(value(), &doubleValue))
- return doubleValue < min;
- } else if (inputType() == RANGE) {
+ if (inputType() == NUMBER || inputType() == RANGE) {
double doubleValue;
if (formStringToDouble(value(), &doubleValue))
- return doubleValue < rangeMinimum();
+ return doubleValue < minimum();
}
return false;
}
bool HTMLInputElement::rangeOverflow() const
{
- if (inputType() == NUMBER) {
- double max = 0.0;
- double doubleValue = 0.0;
- if (formStringToDouble(getAttribute(maxAttr), &max) && formStringToDouble(value(), &doubleValue))
- return doubleValue > max;
- } else if (inputType() == RANGE) {
+ if (inputType() == NUMBER || inputType() == RANGE) {
double doubleValue;
if (formStringToDouble(value(), &doubleValue))
- return doubleValue > rangeMaximum();
+ return doubleValue > maximum();
}
return false;
}
-double HTMLInputElement::rangeMinimum() const
+double HTMLInputElement::minimum() const
{
- ASSERT(inputType() == RANGE);
- // The range type's "default minimum" is 0.
- double min = 0.0;
+ ASSERT(inputType() == NUMBER || inputType() == RANGE);
+ double min = inputType() == RANGE ? rangeDefaultMinimum : numberDefaultMinimum;
formStringToDouble(getAttribute(minAttr), &min);
return min;
}
-double HTMLInputElement::rangeMaximum() const
+double HTMLInputElement::maximum() const
{
- ASSERT(inputType() == RANGE);
- // The range type's "default maximum" is 100.
- static const double defaultMaximum = 100.0;
+ ASSERT(inputType() == NUMBER || inputType() == RANGE);
+ double defaultMaximum = inputType() == RANGE ? rangeDefaultMaximum : numberDefaultMaximum;
double max = defaultMaximum;
formStringToDouble(getAttribute(maxAttr), &max);
- const double min = rangeMinimum();
-
- if (max < min) {
- // A remedy for the inconsistent min/max values.
- // Sets the maxmimum to the default (100.0) or the minimum value.
- max = min < defaultMaximum ? defaultMaximum : min;
+ if (inputType() == RANGE) {
+ // A remedy for the inconsistent min/max values for RANGE.
+ // Sets the maxmimum to the default or the minimum value.
+ double min = minimum();
+ if (max < min)
+ max = std::max(min, defaultMaximum);
}
return max;
}
+double HTMLInputElement::stepBase() const
+{
+ if (inputType() == RANGE)
+ return minimum();
+ if (inputType() == NUMBER) {
+ static const double defaultStepBase = 0.0;
+ double min = defaultStepBase;
+ formStringToDouble(getAttribute(minAttr), &min);
+ return min;
+ }
+ ASSERT_NOT_REACHED();
+ return 0.0;
+}
+
bool HTMLInputElement::stepMismatch() const
{
double step;
@@ -322,9 +331,7 @@ bool HTMLInputElement::stepMismatch() const
double doubleValue;
if (!formStringToDouble(value(), &doubleValue))
return false;
- double stepBase = 0.0;
- formStringToDouble(getAttribute(minAttr), &stepBase);
- doubleValue = fabs(doubleValue - stepBase);
+ doubleValue = fabs(doubleValue - stepBase());
if (isinf(doubleValue))
return false;
// double's fractional part size is DBL_MAN_DIG-bit. If the current
@@ -404,9 +411,59 @@ bool HTMLInputElement::getAllowedValueStep(double* step) const
return true;
}
*step = parsed * stepScaleFactor;
+ ASSERT(*step > 0);
return true;
}
+void HTMLInputElement::applyStepForNumberOrRange(double count, ExceptionCode& ec)
+{
+ ASSERT(inputType() == NUMBER || inputType() == RANGE);
+ double step;
+ if (!getAllowedValueStep(&step)) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+ double current;
+ if (!formStringToDouble(value(), ¤t)) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+ double newValue = current + step * count;
+ if (isinf(newValue)) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+ if (newValue < minimum()) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+ double base = stepBase();
+ newValue = base + round((newValue - base) / step) * step;
+ if (newValue > maximum()) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+ setValue(formStringFromDouble(newValue));
+}
+
+void HTMLInputElement::stepUp(int n, ExceptionCode& ec)
+{
+ if (inputType() != NUMBER && inputType() != RANGE) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+ applyStepForNumberOrRange(n, ec);
+}
+
+void HTMLInputElement::stepDown(int n, ExceptionCode& ec)
+{
+ if (inputType() != NUMBER && inputType() != RANGE) {
+ ec = INVALID_STATE_ERR;
+ return;
+ }
+ applyStepForNumberOrRange(-n, ec);
+}
+
static inline CheckedRadioButtons& checkedRadioButtons(const HTMLInputElement *element)
{
if (HTMLFormElement* form = element->form())
@@ -1997,6 +2054,16 @@ bool HTMLInputElement::willValidate() const
inputType() != BUTTON && inputType() != RESET;
}
+String HTMLInputElement::formStringFromDouble(double number)
+{
+ // According to HTML5, "the best representation of the number n as a floating
+ // point number" is a string produced by applying ToString() to n.
+ DtoaBuffer buffer;
+ unsigned length;
+ doubleToStringInJavaScriptFormat(number, buffer, &length);
+ return String(buffer, length);
+}
+
bool HTMLInputElement::formStringToDouble(const String& src, double* out)
{
// See HTML5 2.4.4.3 `Real numbers.'
diff --git a/WebCore/html/HTMLInputElement.h b/WebCore/html/HTMLInputElement.h
index 14d12bf..8f00aeb 100644
--- a/WebCore/html/HTMLInputElement.h
+++ b/WebCore/html/HTMLInputElement.h
@@ -106,16 +106,21 @@ public:
// For ValidityState
bool rangeUnderflow() const;
bool rangeOverflow() const;
- // Returns the minimum value for type=range. Don't call this for other types.
- double rangeMinimum() const;
- // Returns the maximum value for type=range. Don't call this for other types.
- // This always returns a value which is <= rangeMinimum().
- double rangeMaximum() const;
+ // Returns the minimum value for type=number or range. Don't call this for other types.
+ double minimum() const;
+ // Returns the maximum value for type=number or range. Don't call this for other types.
+ // This always returns a value which is >= minimum().
+ double maximum() const;
// Sets the "allowed value step" defined in the HTML spec to the specified double pointer.
// Returns false if there is no "allowed value step."
bool getAllowedValueStep(double*) const;
// For ValidityState.
bool stepMismatch() const;
+ // Implementations of HTMLInputElement::stepUp() and stepDown().
+ void stepUp(int, ExceptionCode&);
+ void stepDown(int, ExceptionCode&);
+ void stepUp(ExceptionCode& ec) { stepUp(1, ec); }
+ void stepDown(ExceptionCode& ec) { stepDown(1, ec); }
bool isTextButton() const { return m_type == SUBMIT || m_type == RESET || m_type == BUTTON; }
virtual bool isRadioButton() const { return m_type == RADIO; }
@@ -249,6 +254,9 @@ public:
// If the conversion fails, the return value is false. Take care that leading or trailing unnecessary characters make failures. This returns false for an empty string input.
// The double* parameter may be 0.
static bool formStringToDouble(const String&, double*);
+ // Converts the specified number to a string. This is an implementation of
+ // HTML5's "algorithm to convert a number to a string" for NUMBER/RANGE types.
+ static String formStringFromDouble(double);
// Parses the specified string as the InputType, and returns true if it is successfully parsed.
// An instance pointed by the ISODateTime* parameter will have parsed values and be
// modified even if the parsing fails. The ISODateTime* parameter may be 0.
@@ -278,6 +286,11 @@ private:
PassRefPtr<HTMLFormElement> createTemporaryFormForIsIndex();
// Helper for getAllowedValueStep();
bool getStepParameters(double* defaultStep, double* stepScaleFactor) const;
+ // Helper for stepUp()/stepDown(). Adds step value * count to the current number/range value.
+ void applyStepForNumberOrRange(double count, ExceptionCode&);
+ // Helper for applyStepForNumberOrRange().
+ double stepBase() const;
+
#if ENABLE(DATALIST)
HTMLDataListElement* dataList() const;
#endif
diff --git a/WebCore/html/HTMLInputElement.idl b/WebCore/html/HTMLInputElement.idl
index fc03c81..2ac6674 100644
--- a/WebCore/html/HTMLInputElement.idl
+++ b/WebCore/html/HTMLInputElement.idl
@@ -71,6 +71,11 @@ module html {
readonly attribute HTMLOptionElement selectedOption;
#endif
+ void stepUp(in [Optional] long n)
+ raises(DOMException);
+ void stepDown(in [Optional] long n)
+ raises(DOMException);
+
readonly attribute boolean willValidate;
readonly attribute DOMString validationMessage;
boolean checkValidity();
diff --git a/WebCore/rendering/RenderSlider.cpp b/WebCore/rendering/RenderSlider.cpp
index e18b433..b2f5cef 100644
--- a/WebCore/rendering/RenderSlider.cpp
+++ b/WebCore/rendering/RenderSlider.cpp
@@ -82,8 +82,8 @@ SliderRange::SliderRange(HTMLInputElement* element)
} else
hasStep = element->getAllowedValueStep(&step);
- maximum = element->rangeMaximum();
- minimum = element->rangeMinimum();
+ maximum = element->maximum();
+ minimum = element->minimum();
}
double SliderRange::clampValue(double value)
@@ -379,7 +379,7 @@ void RenderSlider::updateFromElement()
bool clamped;
double value = range.valueFromElement(element, &clamped);
if (clamped)
- element->setValueFromRenderer(String::number(value));
+ element->setValueFromRenderer(HTMLInputElement::formStringFromDouble(value));
// Layout will take care of the thumb's size and position.
if (!m_thumb) {
@@ -435,7 +435,7 @@ void RenderSlider::setValueForPosition(int position)
if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart)
fraction = 1 - fraction;
double value = range.clampValue(range.valueFromProportion(fraction));
- element->setValueFromRenderer(String::number(value));
+ element->setValueFromRenderer(HTMLInputElement::formStringFromDouble(value));
// Also update the position if appropriate.
if (position != currentPosition()) {
--
WebKit Debian packaging
More information about the Pkg-webkit-commits
mailing list