mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 635553 (2/2) - <input type='number'> can suffer from a range underflow when @min is set. r=sicking
--HG-- extra : rebase_source : 27045996c62489b28c799d11b6cee5f5df3a2359
This commit is contained in:
parent
1891be27db
commit
535904ed42
@ -815,6 +815,8 @@ nsHTMLInputElement::AfterSetAttr(PRInt32 aNameSpaceID, nsIAtom* aName,
|
|||||||
UpdateTypeMismatchValidityState();
|
UpdateTypeMismatchValidityState();
|
||||||
} else if (aName == nsGkAtoms::max) {
|
} else if (aName == nsGkAtoms::max) {
|
||||||
UpdateRangeOverflowValidityState();
|
UpdateRangeOverflowValidityState();
|
||||||
|
} else if (aName == nsGkAtoms::min) {
|
||||||
|
UpdateRangeUnderflowValidityState();
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateState(aNotify);
|
UpdateState(aNotify);
|
||||||
@ -3800,6 +3802,30 @@ nsHTMLInputElement::IsRangeOverflow() const
|
|||||||
return value > max;
|
return value > max;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsHTMLInputElement::IsRangeUnderflow() const
|
||||||
|
{
|
||||||
|
nsAutoString minStr;
|
||||||
|
if (!DoesMinMaxApply() ||
|
||||||
|
!GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRInt32 ec;
|
||||||
|
double min = minStr.ToDouble(&ec);
|
||||||
|
if (NS_FAILED(ec)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double value = GetValueAsDouble();
|
||||||
|
// value can be NaN when value="".
|
||||||
|
if (value != value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value < min;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHTMLInputElement::UpdateTooLongValidityState()
|
nsHTMLInputElement::UpdateTooLongValidityState()
|
||||||
{
|
{
|
||||||
@ -3884,6 +3910,12 @@ nsHTMLInputElement::UpdateRangeOverflowValidityState()
|
|||||||
SetValidityState(VALIDITY_STATE_RANGE_OVERFLOW, IsRangeOverflow());
|
SetValidityState(VALIDITY_STATE_RANGE_OVERFLOW, IsRangeOverflow());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsHTMLInputElement::UpdateRangeUnderflowValidityState()
|
||||||
|
{
|
||||||
|
SetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW, IsRangeUnderflow());
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHTMLInputElement::UpdateAllValidityStates(bool aNotify)
|
nsHTMLInputElement::UpdateAllValidityStates(bool aNotify)
|
||||||
{
|
{
|
||||||
@ -3893,6 +3925,7 @@ nsHTMLInputElement::UpdateAllValidityStates(bool aNotify)
|
|||||||
UpdateTypeMismatchValidityState();
|
UpdateTypeMismatchValidityState();
|
||||||
UpdatePatternMismatchValidityState();
|
UpdatePatternMismatchValidityState();
|
||||||
UpdateRangeOverflowValidityState();
|
UpdateRangeOverflowValidityState();
|
||||||
|
UpdateRangeUnderflowValidityState();
|
||||||
|
|
||||||
if (validBefore != IsValid()) {
|
if (validBefore != IsValid()) {
|
||||||
UpdateState(aNotify);
|
UpdateState(aNotify);
|
||||||
@ -4020,6 +4053,26 @@ nsHTMLInputElement::GetValidationMessage(nsAString& aValidationMessage,
|
|||||||
aValidationMessage = message;
|
aValidationMessage = message;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case VALIDITY_STATE_RANGE_UNDERFLOW:
|
||||||
|
{
|
||||||
|
nsXPIDLString message;
|
||||||
|
nsAutoString minStr;
|
||||||
|
GetAttr(kNameSpaceID_None, nsGkAtoms::min, minStr);
|
||||||
|
|
||||||
|
// We want to show the double as parsed so we parse it and change minStr.
|
||||||
|
PRInt32 ec;
|
||||||
|
double min = minStr.ToDouble(&ec);
|
||||||
|
NS_ASSERTION(NS_SUCCEEDED(ec), "min must be a number at this point!");
|
||||||
|
minStr.Truncate();
|
||||||
|
minStr.AppendFloat(min);
|
||||||
|
|
||||||
|
const PRUnichar* params[] = { minStr.get() };
|
||||||
|
rv = nsContentUtils::FormatLocalizedString(nsContentUtils::eDOM_PROPERTIES,
|
||||||
|
"FormValidationRangeUnderflow",
|
||||||
|
params, message);
|
||||||
|
aValidationMessage = message;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType);
|
rv = nsIConstraintValidation::GetValidationMessage(aValidationMessage, aType);
|
||||||
}
|
}
|
||||||
|
@ -217,11 +217,13 @@ public:
|
|||||||
bool HasTypeMismatch() const;
|
bool HasTypeMismatch() const;
|
||||||
bool HasPatternMismatch() const;
|
bool HasPatternMismatch() const;
|
||||||
bool IsRangeOverflow() const;
|
bool IsRangeOverflow() const;
|
||||||
|
bool IsRangeUnderflow() const;
|
||||||
void UpdateTooLongValidityState();
|
void UpdateTooLongValidityState();
|
||||||
void UpdateValueMissingValidityState();
|
void UpdateValueMissingValidityState();
|
||||||
void UpdateTypeMismatchValidityState();
|
void UpdateTypeMismatchValidityState();
|
||||||
void UpdatePatternMismatchValidityState();
|
void UpdatePatternMismatchValidityState();
|
||||||
void UpdateRangeOverflowValidityState();
|
void UpdateRangeOverflowValidityState();
|
||||||
|
void UpdateRangeUnderflowValidityState();
|
||||||
void UpdateAllValidityStates(bool aNotify);
|
void UpdateAllValidityStates(bool aNotify);
|
||||||
void UpdateBarredFromConstraintValidation();
|
void UpdateBarredFromConstraintValidation();
|
||||||
nsresult GetValidationMessage(nsAString& aValidationMessage,
|
nsresult GetValidationMessage(nsAString& aValidationMessage,
|
||||||
|
@ -74,6 +74,8 @@ nsIConstraintValidation::GetValidationMessage(nsAString& aValidationMessage)
|
|||||||
GetValidationMessage(aValidationMessage, VALIDITY_STATE_PATTERN_MISMATCH);
|
GetValidationMessage(aValidationMessage, VALIDITY_STATE_PATTERN_MISMATCH);
|
||||||
} else if (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW)) {
|
} else if (GetValidityState(VALIDITY_STATE_RANGE_OVERFLOW)) {
|
||||||
GetValidationMessage(aValidationMessage, VALIDITY_STATE_RANGE_OVERFLOW);
|
GetValidationMessage(aValidationMessage, VALIDITY_STATE_RANGE_OVERFLOW);
|
||||||
|
} else if (GetValidityState(VALIDITY_STATE_RANGE_UNDERFLOW)) {
|
||||||
|
GetValidationMessage(aValidationMessage, VALIDITY_STATE_RANGE_UNDERFLOW);
|
||||||
} else {
|
} else {
|
||||||
// TODO: The other messages have not been written
|
// TODO: The other messages have not been written
|
||||||
// because related constraint validation are not implemented yet.
|
// because related constraint validation are not implemented yet.
|
||||||
|
@ -43,6 +43,7 @@ _TEST_FILES = \
|
|||||||
test_meter_element.html \
|
test_meter_element.html \
|
||||||
test_meter_pseudo-classes.html \
|
test_meter_pseudo-classes.html \
|
||||||
test_max_attribute.html \
|
test_max_attribute.html \
|
||||||
|
test_min_attribute.html \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
libs:: $(_TEST_FILES)
|
libs:: $(_TEST_FILES)
|
||||||
|
152
content/html/content/test/forms/test_min_attribute.html
Normal file
152
content/html/content/test/forms/test_min_attribute.html
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
https://bugzilla.mozilla.org/show_bug.cgi?id=635553
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test for Bug 635553</title>
|
||||||
|
<script type="application/javascript" src="/MochiKit/packed.js"></script>
|
||||||
|
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=635499">Mozilla Bug 635499</a>
|
||||||
|
<p id="display"></p>
|
||||||
|
<div id="content" style="display: none">
|
||||||
|
</div>
|
||||||
|
<pre id="test">
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
/** Test for Bug 635553 **/
|
||||||
|
|
||||||
|
var types = [
|
||||||
|
[ 'hidden', false ],
|
||||||
|
[ 'text', false ],
|
||||||
|
[ 'search', false ],
|
||||||
|
[ 'tel', false ],
|
||||||
|
[ 'url', false ],
|
||||||
|
[ 'email', false ],
|
||||||
|
[ 'password', false ],
|
||||||
|
[ 'datetime', true, true ],
|
||||||
|
[ 'date', true, true ],
|
||||||
|
[ 'month', true, true ],
|
||||||
|
[ 'week', true, true ],
|
||||||
|
[ 'time', true, true ],
|
||||||
|
[ 'datetime-local', true, true ],
|
||||||
|
[ 'number', true ],
|
||||||
|
[ 'range', true, true ],
|
||||||
|
[ 'color', false, true ],
|
||||||
|
[ 'checkbox', false ],
|
||||||
|
[ 'radio', false ],
|
||||||
|
[ 'file', false ],
|
||||||
|
[ 'submit', false ],
|
||||||
|
[ 'image', false ],
|
||||||
|
[ 'reset', false ],
|
||||||
|
[ 'button', false ],
|
||||||
|
];
|
||||||
|
|
||||||
|
var input = document.createElement("input");
|
||||||
|
document.getElementById('content').appendChild(input);
|
||||||
|
|
||||||
|
function checkValidity(aElement, aValidity)
|
||||||
|
{
|
||||||
|
is(aElement.validity.valid, aValidity,
|
||||||
|
"element validity should be " + aValidity);
|
||||||
|
is(aElement.validity.rangeUnderflow, !aValidity,
|
||||||
|
"element underflow status should be " + !aValidity);
|
||||||
|
is(aElement.validationMessage, aValidity
|
||||||
|
? "" : "Please select a value that is higher than " + aElement.min + ".",
|
||||||
|
"validation message");
|
||||||
|
|
||||||
|
is(aElement.mozMatchesSelector(":valid"), aElement.willValidate && aValidity,
|
||||||
|
(aElement.willValidate && aValidity) ? ":valid should apply" : "valid shouldn't apply");
|
||||||
|
is(aElement.mozMatchesSelector(":invalid"), aElement.willValidate && !aValidity,
|
||||||
|
(aElement.wil && aValidity) ? ":invalid shouldn't apply" : "valid should apply");
|
||||||
|
|
||||||
|
// TODO: Add tests for out-of-range / in-range selectors, see bug 635554.
|
||||||
|
}
|
||||||
|
|
||||||
|
for each (var data in types) {
|
||||||
|
input.type = data[0];
|
||||||
|
var apply = data[1];
|
||||||
|
|
||||||
|
if (data[2]) {
|
||||||
|
todo_is(input.type, data[0], data[0] + " isn't implemented yet");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkValidity(input, true);
|
||||||
|
|
||||||
|
input.min = '0';
|
||||||
|
checkValidity(input, true);
|
||||||
|
|
||||||
|
if (input.type == 'url') {
|
||||||
|
input.value = 'http://mozilla.org';
|
||||||
|
checkValidity(input, true);
|
||||||
|
} else if (input.type == 'email') {
|
||||||
|
input.value = 'foo@bar.com';
|
||||||
|
checkValidity(input, true);
|
||||||
|
} else if (input.type == 'file') {
|
||||||
|
// Need privileges to set a filename with .value.
|
||||||
|
netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
|
||||||
|
|
||||||
|
var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]
|
||||||
|
.getService(Components.interfaces.nsIProperties);
|
||||||
|
var file = dirSvc.get("ProfD", Components.interfaces.nsIFile);
|
||||||
|
file.append('635499_file');
|
||||||
|
var outStream = Components.
|
||||||
|
classes["@mozilla.org/network/file-output-stream;1"].
|
||||||
|
createInstance(Components.interfaces.nsIFileOutputStream);
|
||||||
|
outStream.init(file, 0x02 | 0x08 | 0x20, // write, create, truncate
|
||||||
|
0666, 0);
|
||||||
|
outStream.write("foo", 3);
|
||||||
|
outStream.close();
|
||||||
|
|
||||||
|
input.value = file.path;
|
||||||
|
checkValidity(input, true);
|
||||||
|
|
||||||
|
file.remove(false);
|
||||||
|
} else {
|
||||||
|
input.value = '1';
|
||||||
|
checkValidity(input, true);
|
||||||
|
|
||||||
|
input.value = '0';
|
||||||
|
checkValidity(input, true);
|
||||||
|
|
||||||
|
input.value = 'foo';
|
||||||
|
checkValidity(input, true);
|
||||||
|
|
||||||
|
input.value = '-0.1';
|
||||||
|
checkValidity(input, !apply);
|
||||||
|
|
||||||
|
input.min = '-1';
|
||||||
|
checkValidity(input, true);
|
||||||
|
|
||||||
|
input.value = '-42';
|
||||||
|
checkValidity(input, !apply);
|
||||||
|
}
|
||||||
|
|
||||||
|
input.min = '';
|
||||||
|
checkValidity(input, true);
|
||||||
|
|
||||||
|
input.min = 'foo';
|
||||||
|
checkValidity(input, true);
|
||||||
|
|
||||||
|
// Check that we correctly convert input.min to a double in validationMessage.
|
||||||
|
if (input.type == 'number') {
|
||||||
|
input.min = "4.333333333333333333333333333333333331";
|
||||||
|
input.value = "2";
|
||||||
|
is(input.validationMessage,
|
||||||
|
"Please select a value that is higher than 4.33333333333333.",
|
||||||
|
"validation message");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleaning up,
|
||||||
|
input.removeAttribute('min');
|
||||||
|
input.value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -42,6 +42,8 @@ FormValidationPatternMismatch=Please match the requested format.
|
|||||||
FormValidationPatternMismatchWithTitle=Please match the requested format: %S.
|
FormValidationPatternMismatchWithTitle=Please match the requested format: %S.
|
||||||
# LOCALIZATION NOTE (FormValidationRangeOverflow): %S can be a number or a date.
|
# LOCALIZATION NOTE (FormValidationRangeOverflow): %S can be a number or a date.
|
||||||
FormValidationRangeOverflow=Please select a value that is lower than %S.
|
FormValidationRangeOverflow=Please select a value that is lower than %S.
|
||||||
|
# LOCALIZATION NOTE (FormValidationRangeUnderflow): %S can be a number or a date.
|
||||||
|
FormValidationRangeUnderflow=Please select a value that is higher than %S.
|
||||||
GetAttributeNodeWarning=Use of getAttributeNode() is deprecated. Use getAttribute() instead.
|
GetAttributeNodeWarning=Use of getAttributeNode() is deprecated. Use getAttribute() instead.
|
||||||
SetAttributeNodeWarning=Use of setAttributeNode() is deprecated. Use setAttribute() instead.
|
SetAttributeNodeWarning=Use of setAttributeNode() is deprecated. Use setAttribute() instead.
|
||||||
GetAttributeNodeNSWarning=Use of getAttributeNodeNS() is deprecated. Use getAttributeNS() instead.
|
GetAttributeNodeNSWarning=Use of getAttributeNodeNS() is deprecated. Use getAttributeNS() instead.
|
||||||
|
Loading…
Reference in New Issue
Block a user